欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WPF绑定概念基础(四大组成,绑定方向,绑定触发)

程序员文章站 2022-06-07 18:08:22
...

    本文为原创文章,可以转载但不得商用,转载必须注明来源。

    今天讲述的是一个关于WPF绑定的小例子,学习好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}"

   是告知两个控件绑定的路径,至此我们一定要牢记绑定的四大组成部分(一定要牢记):

  1. 绑定源,这里例子是mcl;记住绑定源指的是对象;
  2. 绑定路径,可以完全理解为绑定源的某个属性,在本例子里就是myClass类型的mytext属性。记住绑定路径指的是绑定源对象里的某个属性;
  3. 绑定目标对象,这里例子是TextBox和TextBlock对象;
  4. 绑定目标属性,这里的例子是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,绑定源属性的值在初始时绑定到绑定目标属性的值上,后面不再有任何影响。
(4)但凡源想改变目标:也就是方向Mode属性是OneWay和TwoWay这两种类型来说,如果希望绑定源的每一次改变都能反映到绑定目标的属性值的改变上,那么您需要实现INotifyPropertyChanged接口。重新说一遍:如果你希望绑定源属性值(本例子为mytext属性)的更新能够自动反应到控件当中(也就是绑定源属性的值的改变能够同步改变到绑定目标属性的值),那么抱歉,WPF框架下,您必须得自己来实现INotifyPropertyChanged接口,这句话也是需要您牢记的,这也是告诉您WPF还没有那么智能,您需要自己额外写一点代码,反正您只要按照这个接口实现了,您的属性值改变就可以自动影响界面的变化了,神奇的原因在于WPF框架内部都做好了。当然,您也不必费脑细胞去记清楚这个接口实现的细节,你只要牢记这种情形下必须得自己来实现INotifyPropertyChanged接口(至此重要的事情又说了三遍),真正实现百度一下或者查微软官网资料即可,您仅需要记住INotifyPropertyChanged这个WPF单词
  • 控件的每个依赖项属性都有默认的绑定方向,一一记住是不可能的,大致可以通过是否可编辑来大致判断属性值的绑定方向,如果是可编辑的那么相应的属性值是TwoWay方向,如果是不可编辑的一般来讲是OneWay。您也可以通过方法查询特定控件特定属性的默认绑定方向,这里不做详细说明。因此,该例子的TextBox的Text属性默认方向是TwoWay,而TextBlock的Text属性默认方向是OneWay。
  • 也就是目标反过来想改变源:也就是方向Mode属性是OneWayToSource或者TwoWay,这种情况下还涉及到Binding类型对象的UpdateSourceTrigger属性,它就是表示源影响目标的触发方式。UpdateSourceTrigger触发类型又分为三种:
    • LostFocus,当控件失去焦点时改变源属性值;
    • PropertyChanged,每当控件的属性值改变都立即改变源属性值;
    • Explicit,用户自己通过调用UpdateSource方法来改变源属性的值,控制权在用户手上。

   该例子中,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绑定的一些基本内容先讲到这,绑定还有很多其他内容,但这是最基础的知识,希望大家可以掌握。谢谢!

相关标签: 绑定 WPF