WPF绑定概念基础(四大组成,绑定方向,绑定触发)
本文为原创文章,可以转载但不得商用,转载必须注明来源。
今天讲述的是一个关于WPF绑定的小例子,学习好WPF绑定,几乎可以达到逻辑和界面完全隔离的神奇效果。
关于逻辑和界面是否可以完全可以隔离,我想告诉大家的是,如果学好了绑定机制和内部运行原理,是可以达到的,这是微软的能力!
先讲本文例子呈现的效果:
第一个例子:
第二个例子:
先讲一下第一个例子:
XMAL文件中的代码如下所示:
<Grid Name="mygrid">
<StackPanel>
<TextBox Text="{Binding mytext}" Width="100" Margin="5"></TextBox>
<TextBlock Text="{Binding mytext}" Margin="5,0,5,5" Width="100" Background="NavajoWhite"></TextBlock>
<Button Width="100">click</Button>
</StackPanel>
</Grid>
如上代码所示,TextBox控件的依赖项属性Text绑定到mytext,TextBlock的依赖项属性Text也是绑定到mytext (这就相当于告诉大家,同一个绑定源可以同时绑定到多个绑定目标), mytext是MainWindows中的一个自定义的myClass对象mcl的string类型的属性,其代码如下所示:
public partial class MainWindow : Window
{
public myClass mcl { get; set; } = new myClass();
public MainWindow()
{
InitializeComponent();
mcl.mytext = "hello";
mygrid.DataContext = mcl;//需要给mygrid控件指定DataContext为mcl,这是告诉Grid控件以及它子控件绑定源是谁
}
}
public class myClass:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _mytext;
public string mytext {
get
{ return _mytext; }
set
{
_mytext = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("mytext"));
}
}
}
这个例子下,用户在TextBox框中输入字符串,只有当用户接着点击一下按钮或者将输入焦点改变到其他地方,TextBlox的字符串才会改变成和TextBox输入框的字符串一样。
下面在进入第二个例子前,先讲一些有非常用的绑定知识:
如上图所示,设置DataContext属性是为了告知绑定源对象,TextBox和TextBlock控件可以继承了来自Grid的绑定源。XMAL代码中的
Text="{Binding mytext}"
是告知两个控件绑定的路径,至此我们一定要牢记绑定的四大组成部分(一定要牢记):
- 绑定源,这里例子是mcl;记住绑定源指的是对象;
- 绑定路径,可以完全理解为绑定源的某个属性,在本例子里就是myClass类型的mytext属性。记住绑定路径指的是绑定源对象里的某个属性;
- 绑定目标对象,这里例子是TextBox和TextBlock对象;
- 绑定目标属性,这里的例子是TextBox和TextBlock对象的Text属性;记住目标属性一定是依赖项属性。
根据微软官方文件,对于这个例子,需要了解的理论知识:
(1)XMAL代码中出现的Binding扩展标记内的Path路径指定应当是指向一个对象的public 属性,Binding扩展标记中第一个参数可以省略Path:Text="{Binding mytext}"
等价于:
Text="{Binding Path=mytext}"
(2)记住绑定目标属性一定是依赖项属性。这是第二遍强调了。绝大部分控件的属性都是依赖项属性。这也是告诉你如果你想自己实现一个自定义控件的属性,并且希望这个属性也可以像WPF官方控件一样绑定一个绑定源,那么你也要按照依赖项属性形式实现一个属性,关于依赖项属性的概念可以查看其它官网或百度资料,未来有空也会写一下这方面的知识,这里仅需要大家牢记的是绑定目标的属性必须是一个依赖项属性,不可辩驳!重要的事情说三遍。本篇文章看了能记住这一条你就比昨天进步了一点。(3)绑定流方向,绑定流方向是由Binding类对象的Mode属性设置的,它共有四种方向:
- OneWay,绑定源的属性值可以影响绑定目标属性的值;
- TwoWay,绑定源的属性值可以影响绑定目标属性的值,同样的绑定目标属性的值改变了也会影响绑定源属性的值;
- OneWayToSource,绑定目标属性的值改变可以影响绑定源属性的值;
- OneTime,绑定源属性的值在初始时绑定到绑定目标属性的值上,后面不再有任何影响。
- 控件的每个依赖项属性都有默认的绑定方向,一一记住是不可能的,大致可以通过是否可编辑来大致判断属性值的绑定方向,如果是可编辑的那么相应的属性值是TwoWay方向,如果是不可编辑的一般来讲是OneWay。您也可以通过方法查询特定控件特定属性的默认绑定方向,这里不做详细说明。因此,该例子的TextBox的Text属性默认方向是TwoWay,而TextBlock的Text属性默认方向是OneWay。
- 也就是目标反过来想改变源:也就是方向Mode属性是OneWayToSource或者TwoWay,这种情况下还涉及到Binding类型对象的UpdateSourceTrigger属性,它就是表示源影响目标的触发方式。UpdateSourceTrigger触发类型又分为三种:
- LostFocus,当控件失去焦点时改变源属性值;
- PropertyChanged,每当控件的属性值改变都立即改变源属性值;
- Explicit,用户自己通过调用UpdateSource方法来改变源属性的值,控制权在用户手上。
- LostFocus,当控件失去焦点时改变源属性值;
该例子中,TextBox的UpdateSourceTrigger属性是默认是LostFocus,因此例子一当中不需要明确设置UpdateSourceTrigger值。
至此我们就可以完全理解例子一的绑定效果了,它的过程时这样子的:
TextBox和TextBlock都绑定到实现了INotifyPropertyChanged接口的myClass类的mytext属性上,由于TextBox绑定方向是TwoWay的,因此在TextBox输入框中改变值之后,然后点击按钮让TextBox输入框失去焦点,这个时候mytext值立即被改变,由于与TextBlock的绑定方向是OneWay,mytext值的改变立即影响了TextBlock,至此说明了整个绑定的基本细节。
好,说了这么多,大家可以猜到如何在例子一上做改动实现例子二了吧。很好,有些同学可能猜到了,只需要改XMAL中的一处即可:
<Grid Name="mygrid">
<StackPanel>
<TextBox Text="{Binding mytext,UpdateSourceTrigger=PropertyChanged}" Width="100" Margin="5"></TextBox>
<TextBlock Text="{Binding mytext}" Margin="5,0,5,5" Width="100" Background="NavajoWhite"></TextBlock>
<Button Width="100">click</Button>
</StackPanel>
</Grid>
如上所示,在TextBox的Text属性的Binding扩展标记中添加UpdateSourceTrigger=PropertyChanged即可,这个时候只要用户在TextBox的输入框中改变内容就会立即反应到TextBlock当中。
WPF绑定的一些基本内容先讲到这,绑定还有很多其他内容,但这是最基础的知识,希望大家可以掌握。谢谢!