对应WPF编程宝典 第八章 第十九章 第二十章
本笔记仅供自己查漏补缺使用,在记录的过程中可能会侧重How而忽略Why和What。
基础绑定
首先来看下绑定的实现类 Binding类,在PresentationFramework程序集的 System.Windows.Data命名空间下
其中 Mode、Path、ElementName、Source、Converter 是我们最常用的参数,在XAML中可以直接赋值。
Path
指向目标属性的路径,可以是属性的名称,也可以是属性的属性,也可以包含属性的索引器。
如果希望引用附加属性,那么需要使用”()”封装属性的名称。比如使用(Grid.Row)
来绑定元素的行号绑定到附加属性。
该属性只需要指向属性或者依赖属性都可以,但是要注意对应属性的访问修饰符。
Source
Source是指绑定的属性的来源的对象,提供对象的数据,可以通过多种方式设置。
1.使用ElementName绑定到文档中的其他元素时
可以使用ElementName属性指定对象的名称。
<TextBox Text="Binding ElementNamme=Window,Path=Title"/>
2.使用Source绑定到静态对象
可以使用Source属性指向目标
<TextBox Text="{Binding Source={x:Static System.IconFontFamily},Path=Source}"
这个表达式将静态属性SystemFonts.IconFontFamily提供的Fontmaily对象设置为了Binding.Source,并且将Path设置为FontFamily.Source,从而得到了字体家族的名称。
3.使用RelativeSource绑定到父元素
RelativeSource的Mode属性具有多种枚举,总计4种模式
名称 | 说明 |
---|---|
Self | 绑定到自身元素 |
FindAncetor | 绑定到父元素。 搭配AncetorType与AncetorLevel使用 |
PreviousData | 列表项中可用,绑定列表种的前一个数据项。 |
TemplateParent | 绑定到应用模板的元素。仅当位于模板内部时才能使用。 |
4.缺省Source设置,自动获取DataContext
当表达式中省略了数据源信息时,WPF会检查元素的DataContext属性,如果为Null会继续在元素树向上寻找第一个部位Null的DataContext。
这是因为DataContext是依赖属性,当自身为空时会顺着树结构读取父元素的DataContext属性。
Mode
在设置Binding的时候可用为其设置BindingMode,该属性为枚举值。
OneWay | 数据源发生变化时更新目标 | |
---|---|---|
TwoWay | 数据源发生变化时更新目标,目标发生变化时更新数据源 | |
OneTime | 根据绑定时的源属性值设置目标属性。 | 确定原属性不会变化时可用使用,可用降低开销。 |
OneWayToSource | 目标发生变化时更新数据源 | 提供数值的属性必须是依赖属性。 |
Default | 取决于依赖属性的默认值。 | 取决于依赖属性中的元数据。FrameworkProperyMetadata.BindsTwoWayByDefault 标识。 |
绑定更新&绑定延迟
绑定更新
在TwoWay和OneWayToSource的绑定模式中,可通过UpdateSourceTrigger属性控制触发更新目标属性的时机。
- PropertyChanged 属性变更时立即更新
- LostFocus 当属性发生变化 且 目标丢失焦点时更新
- Explict 手动调用BindingExpression.UpdateSource()时才更新
Default 根据目标属性的元数据确定行为,大多数属性默认是PopertyChanged,TextBox.Text是LostFocus
绑定延迟
可以为绑定设置Delay属性,避免过分频繁的触发属性变更操作。
这里的500单位为毫秒,会在用户输入停止后500毫秒触发更新。<TextBox Text="{Binding Path=FontSize,Delay=500}"
变更通知
依赖属性
实现变更通知的方法有多种多样,其中一种是使用依赖属性,依赖属性天生支持变更通知,但这并非最自然的方式。
INotifyPropertyChanged接口
手动实现
class NotifyObject : INotifyPropertyChanged
{
private int number;
public int Number
{
get { return number; }
set { number = value; OnPropertyChanged("Number"); }
}
private string text;
public string Text
{
get { return text; }
set { text = value; OnPropertyChanged("Text"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName = "")
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
使用Fody在编译时自动实现
- 安装 PropertyChanged.Fody库
- 为目标类添加 [ImplementPropertyChanged] 注解,编译后的代码会自动实现INotifyPropertyChanged ```csharp [ImplementPropertyChanged] public class Person {
public string GivenNames { get; set; } public string FamilyName { get; set; }
public string FullName => string.Format(“{0} {1}”, GivenNames, FamilyName); }
实际上各种Mvvm框架中也有自己的实现INotifyPropertyChanged方法,比如Prism是通过`SetProperty(ref xxx,Value)` 来代替Set器中的内容实现的,开发中需要结合自己的情况决定采用哪种方式。
<a name="eaPd7"></a>
### 检索BindingExpression.UpdateTarget()
最笨拙的方法
1. 通过FrameworkElement.GetBindingExpression() 获取绑定。
1. 调用BindingExpression.UpdateTarget()方法来触发更新。
<a name="EMTjI"></a>
## 数据验证
讲道理这东西我没用过....
<a name="3rFqc"></a>
## NULL值绑定
WPF对于NULL值的默认处理是 不显示任何内容。<br />可以通过TargetNullValue属性改变WPF对Null值的处理方式,如下,当绑定的数据源为Null时,将显示在TargetNullValue中提供的值。
```xml
Text ="{Binding Path=Description, TargetNullValue=No Description Provided}"
数据转换
值转换器
之转换器是实现了IValueConverter接口的类,原理如下
通常是在Window/Usercontrol 的Resourse中创建一个转换器。在创建转换器的时候还可以为转换器中的public属性赋值。
如
多属性转换器
多属性转换器需要使用IMultiValueConverter,在绑定的时候也要使用MultBinding,如下
需要注意的是 在Converter中拿到的是Values[] 数组,顺序是按照Binding中传入的顺序排列
StringFormat属性
通过设置Binding.StringFormat 对文本格式的数据进行转换。
在使用StringFormat的时候要注意下以下几点。
当StringFormat 以空格 或者没有其他值开头时,需要使用”{}”在最前面进行转义。如
StringFormat={}{0:C}
StringFormat同转换器一样,支持多个属性。写法如下
<TextBlock>
<TextBlock.Text>
<MultiBinding stringFormat="{1},{0}"]>
<Binding Path="FirstName"></Binding>
<Binding Path="LastName"></Binding>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
常见转义如下。