WPF 中的数据绑定功能与传统模型相比具有一些优势,包括本质上支持数据绑定的各种属性、灵活的数据 UI 表示形式,以及业务逻辑与 UI 的完全分离。
数据绑定是在应用程序 UI 与业务逻辑之间建立连接的过程。 如果绑定具有正确设置并且数据提供正确通知,则当数据更改其值时,绑定到数据的元素会自动反映更改。 数据绑定可能还意味着如果元素中数据的外部表现形式发生更改,则基础数据可以自动更新以反映更改。 例如,如果用户编辑 TextBox 元素中的值,则基础数据值会自动更新以反映该更改。
1. 数据绑定基础
1.1 数据绑定模型
- 目标属性必须是依赖属性。
- 绑定源 对象并不限于自定义 CLR 对象。 WPF 数据绑定支持 CLR 对象和 XML 形式的数据。 举例来说,绑定源可以是 UIElement、任何列表对象、与 ADO.NET 数据或 Web 服务关联的 CLR 对象,也可以是包含 XML 数据的 XmlNode。
1.2 数据绑定方向
Mode包括:
成员名称 | 说明 |
TwoWay | 导致对源属性或目标属性的更改可自动更新对方。 此绑定类型适用于可编辑窗体或其他完全交互式 UI 方案。 |
OneWay | 当绑定源(源)更改时,更新绑定目标(目标)属性。 如果要绑定的控件为隐式只读控件,则适用此绑定类型。 例如,可以绑定到如股市代号之类的源。 或者,可能目标属性没有用于进行更改(例如表的数据绑定背景色)的控件接口。 如果不需要监视目标属性的更改,则使用 OneWay 绑定模式可避免 TwoWay 绑定模式的系统开销。 |
OneTime | 当应用程序启动或数据上下文更改时,更新绑定目标。 此绑定类型适用于以下情况:使用当前状态的快照适合使用的或数据状态实际为静态的数据。 如果要从源属性初始化具有某个值的目标属性,并且事先不知道数据上下文,则也可以使用此绑定类型。 实质上,这是 OneWay 绑定的较简单的形式,它在不更改源值的情况下可提供更好的性能。 |
OneWayToSource | 当目标属性更改时更新源属性。与OneWay相反。 |
Default | 使用绑定目标的默认 Mode 值。 每个依赖项属性的默认值都不同。 一般情况下,用户可编辑控件属性(例如文本框和复选框的属性)默认为双向绑定,而多数其他属性默认为单向绑定。 确定依赖项属性绑定在默认情况下是单向还是双向的编程方法是:使用 GetMetadata 来获取属性的属性元数据,然后检查 BindsTwoWayByDefault 属性的布尔值。也可通过MSDN查看对应依赖属性的信息中设置为 true 的元数据属性。 |
1.3 数据绑定的触发条件
成员名称 | 说明 |
Default | 绑定目标属性的默认 UpdateSourceTrigger值。多数依赖项属性的默认值为 PropertyChanged,而 Text属性的默认值为 LostFocus。 确定依赖项属性的默认 UpdateSourceTrigger值的编程方法是使用 GetMetadata来获取属性的属性元数据,然后检查 DefaultUpdateSourceTrigger属性的值。 |
PropertyChanged | 当绑定目标属性更改时,立即更新绑定源。 |
LostFocus | 当绑定目标元素失去焦点时,更新绑定源。 |
Explicit | 仅在调用 UpdateSource方法时更新绑定源。 |
1.4 数据绑定实例
将第一个文本框的Text属性绑定到第二个文本框的Text属性即可。
Text="{Binding Path=Text,ElementName=txtBox2,Mode=Default,UpdateSourceTrigger=PropertyChanged}"
程序代码中使用
txtBox1.SetBinding(TextBox.TextProperty, new Binding("Text")
{
ElementName="txtBox2",
//Mode=BindingMode.Default,
UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged
});
1.5小结
通过下面的编程方法来获得他们的Default值(以下为即时窗口调试输出结果):
{System.Windows.FrameworkPropertyMetadata}
[System.Windows.FrameworkPropertyMetadata]: {System.Windows.FrameworkPropertyMetadata}
CoerceValueCallback: {Method = {System.Object CoerceText(System.Windows.DependencyObject, System.Object)}}
DefaultValue: ""
PropertyChangedCallback: {Method = {Void OnTextPropertyChanged(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)}}
(TextBox.TextProperty.GetMetadata(txtBox1) as System.Windows.FrameworkPropertyMetadata).BindsTwoWayByDefault
true
(TextBox.TextProperty.GetMetadata(txtBox1) as System.Windows.FrameworkPropertyMetadata).DefaultUpdateSourceTrigger
LostFocus
2. 绑定数据源的4种方式
- Source
<Window.Resources>
<local:Student x:Key="student" id="01" name="小丽"/>
</Window.Resources>
Text="{Binding Path=id,Source={StaticResource student}}"
- ElementName
- RelativeSource
成员名称 | 说明 |
PreviousData | 允许您绑定所显示数据项列表中以前的数据项(不是包含数据项的控件)。 |
TemplatedParent | 引用应用了模板(其中有数据绑定元素)的元素。这类似于设置 TemplateBindingExtension,并仅当 Binding在模板中时适用。 |
Self | 引用您对其设置绑定的元素,并允许您将该元素的一个属性绑定到同一元素中的其他属性。 |
FindAncestor | 引用数据绑定元素父链中的上级。您可以使用它绑定到特定类型或其子类的上级。如果您要指定 AncestorType和/或 AncestorLevel,可以使用此模式。 |
- DataContext
this.DataContext = this;
Text="{Binding stu.id}"
3. 数据更改通知
虽然将数据绑定的方向规定为OneWay或者TwoWay,但是数据源没有一种机制通知目标,属性发送改变后目标是得不到相应的更新的。通常解决这个问题有两种方法。
- 将数据源属性实现为依赖属性。此法多用于元素之间,对于Person这种类型,此法不合适。
- 数据源实现INotifyPropertyChanged接口。
public class Student : INotifyPropertyChanged
{
private string _id;
public string id
{
get { return _id; }
set
{
_id = value;
NotifyPropertyChanged("id");
}
}
public string name { get; set; }
public Sex sex{ get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
效果图
4. 数据转换器(ValueConverter)
public class SexConverter : IValueConverter
{
//绑定属性-->目标属性
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string sex = "其他";
if(value is Sex)
{
sex = (Sex)value == Sex.Boy ? "男" : ((Sex)value == Sex.Girl ? "女" : "其他");
}
return sex;
}
//目标属性-->绑定属性
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.ToString().Trim() == "男" ? Sex.Boy : (value.ToString().Trim() == "女" ? Sex.Girl : Sex.Other);
}
}
<TextBox HorizontalAlignment="Left" Height="32" Margin="31,137,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="227"
Text="{Binding stu.sex,Converter={StaticResource sexConverter}}"/>
5.数据验证
5.1 创建验证规则
ValidationRule 对象可检查属性的值是否有效。 WPF 具有以下两种类型的内置 ValidationRule 对象:ExceptionValidationRule 检查在更新绑定源属性的过程中引发的异常。 在前面的示例中,StartPrice 为整数类型。 当用户输入的值无法转换为整数时,将引发异常,这会 导致将绑定标记为无效。 用于显式设置 ExceptionValidationRule 的可选语法是将 Binding 或 MultiBinding 对象上的 ValidatesOnExceptions 属性设置为 true。
DataErrorValidationRule 对象检查由实现 IDataErrorInfo 接口的对象所引发的错误。 有关使用此验证规则的示例,请参见 DataErrorValidationRule。 用于显式设置 DataErrorValidationRule 的可选语法是将 Binding 或 MultiBinding 对象上的 ValidatesOnDataErrors 属性设置为 true。
5.1.1 自定义验证规则
可以通过从 ValidationRule 类派生和实现 Validate 方法来创建自己的验证规则。class IdRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if(string.IsNullOrWhiteSpace(value.ToString()))
{
return new ValidationResult(false, "代码不能为。");
}
else
{
Regex regex = new Regex(@"^\d+$");
if(regex.IsMatch(value.ToString()))
{
return ValidationResult.ValidResult;
}
else
{
return new ValidationResult(false, "代码只能输入数字。");
}
}
}
}
XAML中使用
<TextBox HorizontalAlignment="Left" Height="29" Margin="124,216,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="247">
<TextBox.Text>
<Binding Path="stu.id">
<Binding.ValidationRules>
<local:IdRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
5.2验证提示方法
5.2.1使用附加属性Validation.ErrorTemplate
<ControlTemplate x:Key="validationTemplate">
<DockPanel>
<TextBlock Foreground="Red" FontSize="20">!</TextBlock>
<AdornedElementPlaceholder/>
</DockPanel>
</ControlTemplate>
5.2.2使用ToolTip
<Style x:Key="textStyleTextBox" TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
验证的
TextBox
的
XAML
代码
<TextBox HorizontalAlignment="Left" Height="29" Margin="124,216,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="247"
Validation.ErrorTemplate="{StaticResource validationTemplate}"
Style="{StaticResource textStyleTextBox}">
<TextBox.Text>
<Binding Path="stu.id">
<Binding.ValidationRules>
<local:IdRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
效果
作者:FoolRabbit
出处:http://blog.csdn.net/rabbitsoft_1987
欢迎任何形式的转载,未经作者同意,请保留此段声明!