WPF Binding学习(二)

  Binding作为数据的桥梁,连通业务逻辑层的对象(源对象)和UI的控件对象(目标对象)。在这座桥梁上,我们不仅可以控制在源对象与目标对象是双向通行还是单向通行。还可以控制数据的放行时机,甚至可以在这座桥上搭建一些关卡用来转换数据类型或者检验数据的正确性

我们先做一个最基本的例子,

创建一个"Student"类,这个类的实例将作为数据源来使用

 public class Student
    {
        private int _id;

        public int ID
        {
            get { return _id; }
            set { _id = value; }
        }
        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        private int _age;

        public int Age
        {
            get { return _age; }
            set { _age = value; }
        }

    }

然后我们编写我们的控件对象和创建逻辑对象

  <StackPanel Name="stack1">
        <TextBox Width="120" Text="{Binding Path=ID}" HorizontalAlignment="Left" Name="txt_ID"></TextBox>
        <TextBox  Width="120" Text="{Binding Path=Name}" HorizontalAlignment="Left" Name="txt_Name" ></TextBox>
        <TextBox  Text="{Binding Path=Age}" Width="120" HorizontalAlignment="Left" Name="txt_Age"></TextBox>
   </StackPanel>
 public Student Stu;
        public MainWindow()
        {
            InitializeComponent();
            Stu = new Student { ID = 1, Name = "狗娃", Age = 11 };       //设置元素数据绑定对象
            stack1.DataContext = Stu;
        }

我们可以看到TextBox控件的Text是一个{Binding} 这就是数据绑定的关键字。然后Path属性是需要绑定的属性,然后我们运行就可以看到我们已经绑定OK。

上面我们是使用的界面进行绑定,其实我们还可以使用代码对每一个控件进行绑定。现在我们将WPF界面中的绑定删除掉

 <StackPanel Name="stack1">
        <TextBox Width="120"  HorizontalAlignment="Left" Name="txt_ID"></TextBox>
        <TextBox  Width="120"  HorizontalAlignment="Left" Name="txt_Name" ></TextBox>
        <TextBox  Width="120" HorizontalAlignment="Left" Name="txt_Age"></TextBox>
    </StackPanel>

然后我们使用代码来进行控件绑定

  public Student Stu;
  public MainWindow()
  {
            InitializeComponent();
            Stu = new Student { ID = 1, Name = "狗娃", Age = 11 };
            //创建Binding对象.
            Binding bindingID = new Binding() {Path = new PropertyPath("ID"),Source=Stu };
            //Binding构造参数可以直接传入Path参数
            Binding bindingName = new Binding("Name") { Source = Stu };
            Binding bindingAge = new Binding("Age") { Source = Stu };

            //进行控件绑定(第一个参数是将绑定到哪个属性,第二个参数是绑定对象)
            this.txt_ID.SetBinding(TextBox.TextProperty, bindingID);
            this.txt_Name.SetBinding(TextBox.TextProperty, bindingName);
            this.txt_Age.SetBinding(TextBox.TextProperty,bindingAge);
   }

可以看到使用代码绑定需要创建Binding对象,然后使用控件的SetBinding方法进行绑定,但是郁闷的我们为了绑定这三个属性要写这么多的代码.所以使用哪种方式绑定看需求来使用.

接下来我们看双向绑定,其实上面那个我们已经实现了双向绑定,我们先做一个例子测试

创建一个测试TextBox并绑定数据ID

<TextBox Width="120"  HorizontalAlignment="Left"  Name="txt_IDTest"></TextBox>
 Binding bindingTestID = new Binding() { Path = new PropertyPath("ID"), Source = Stu };
 this.txt_IDTest.SetBinding(TextBox.TextProperty, bindingTestID);

然后我们在更改txt_ID属性值后光标离开就可以看到txt_IDTest的值也随之改变了。这是因为TextBox默认是双向绑定的,所以可以改变,但是如果我们不是使用控件改变的值呢,接下来做个这样例子.在界面上添加一个Button按钮,并添加点击事件

<Button Content="Button" Width="120" HorizontalAlignment="Left" Click="Button_Click"/>
 private void Button_Click(object sender, RoutedEventArgs e)
        {

            Stu.ID++;
        }

我们在点击事件中只做了一件事,那就是让Stu的编号加1,但是运行会发现并没有改变。那么该怎么做呢。

我们需要在绑定源类型(Student类型)实现INotifyPropertyChanged接口

public class Student:INotifyPropertyChanged
    {
        private int _id;

        public int ID
        {
            get { return _id; }
            set { _id = value; MyPropertyChanged(nameof(ID)); }
        }

        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; MyPropertyChanged(nameof(Name)); }
        }

        private int _age;

        public event PropertyChangedEventHandler PropertyChanged;

        public int Age
        {
            get { return _age; }
            set { _age = value; MyPropertyChanged(nameof(Age)); }
        }
        private void MyPropertyChanged(string name)
        {
           if(PropertyChanged!=null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

然后此时我们就可以实现改变了.

2.绑定更新的计时

但是我们往往需要在输入后就让它立即改变,所以我们需要设置Binding对象中的UpdateSourceTrigger属性,

  Binding bindingID = new Binding() { Path = new PropertyPath("ID"), Source = Stu, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged};

UpdateSourceTrigger枚举值有4个

  • Default:绑定目标属性的默认值
  • PropertyChanged:每当绑定目标属性发生改变时,都会更新数据源
  • LostFocus:每当绑定目标元素失去焦点时,都会更新绑定源
  • Explicit:仅在调用System.Windows.Data.BindingExpression.UpdateSource 方法时更新绑定源。

因此我们将UpdateSourceTrigger的属性值改成PropertyChanged即可

3.设置单项和双向绑定

刚才使用了TextBox的双向绑定,但是比如我们现在不需要双向绑定,我们只需设置Mode属性即可

 Binding bindingID = new Binding() { Path = new PropertyPath("ID"), Source = Stu,Mode = BindingMode.OneTime, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged};

BindingMode枚举有5个值

  • TwoWay:导致更新源属性或目标属性时自动更新另一方
  • OneWay:在更改绑定源(源)时更新绑定目标(目标),如果绑定的控件为隐式只读,则此类型的绑定适用。如果无需监视目标属性的更改  则使用 System.Windows.Data.BindingMode.OneWay 绑定模式可避免 System.Windows.Data.BindingMode.TwoWay

    绑定模式的系统开销。
  • OneTime:这是实质上是 System.Windows.Data.BindingMode.OneWay 绑定的一种简化形式,它在源值不更改的情况下提供更好的性能。
  • OneWayToSource:在目标属性更改时,更新源属性。
  • Default: 使用绑定目标的默认 System.Windows.Data.Binding.Mode 值

原文地址:https://www.cnblogs.com/yan7/p/8315966.html

时间: 2024-10-28 22:19:18

WPF Binding学习(二)的相关文章

WPF Binding学习(三)

转自;http://blog.csdn.net/lisenyang/article/details/18312199 1.控件与控件间的双向绑定 WPF还支持控件作为数据源, <TextBox Name="txt_Source" Width="120" HorizontalAlignment="Left"></TextBox> <TextBox Text="{Binding ElementName=txt_

WPF Binding学习(四) 绑定各种数据源

1.集合作为数据源 首先我们先创建一个模型类 public class Student { public int ID { get; set; } public String Name { get; set; } } 然后我们创建我们的页面布局 <StackPanel Width="300" Height="300" HorizontalAlignment="Left"> <ListView Name="listVie

WPF的Binding学习笔记(二)

原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的皮毛, 然后就做别的事去了, 等回头再来看WPF的时候, 哈忘记了~ 于是写个例子补一下, 在继续学习Binding. 1, 首先准备好一个类 public class Hero { public Hero(int id, string name, string skill, bool hasM)

WPF入门教程系列(二) 深入剖析WPF Binding的使用方法

WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProperty)只能拥有一个binding. 这一点可以通过设置binding对象的方法名得知: public static BindingExpressionBase SetBinding( DependencyObject target, DependencyProperty dp, BindingB

WPF Binding值转换器ValueConverter使用简介(二)-IMultiValueConverter

注: 需要继承IMultiValueConverter接口,接口使用和IValueConverter逻辑相同. 一.MultiBinding+Converter 多值绑定及多值转换实例 当纵向流量大于横向流量时指示灯应为绿色,当纵向流量小于横向流量时指示灯应为红色,否则指示灯为黄色. 1.定制ColorConverter类,此时Convert中参数是object[] values,values[0]对应MultiBinding中的第一个Binding值,这里是纵向流量值,依此类推,可以在Mult

WPF学习二:TextBlock和Label的区别

TextBlock和Label都是用来显示少量数据的.好多文章对Label存在的描述都是它允许使用"快速获取"."快速获取"就是允许你用Alt加上其它的按键快速和UI界面的某个控件交互,比如你可以用ALT加上O键来点击一个OK按钮. TextBlock直接继承于FrameworkElement,而Label继承于ContentControl.这样看来,Label可以做这样的事情: 1.可以定义一个控件模板(通过Template属性) 2.可以显示出string以外的

WPF基础学习笔记(一)Dependency Object 和 Dependency Property

.依赖属性是WPF个人觉得对精彩和最有特色的部分.所以特地先拿出来. 首先要实现Dependency Property 则必须要继承Dependency Object.如果看下WPF的基础控件其实都间接或者直接继承Dependency Object,这点规律性我在后面再做规律陈述. 首先Dependency Object 我搬下书的描述 Only the thread that the Dispatcher was created on may access the DispatcherObje

WPF系列之二:解耦View层控件事件与ViewModel层事件的响应

以前的做法: 1.当项目的时间比较紧迫的时候,对UI层中控件的事件的处理,往往采取的是类似Winform中最简单的做法,直接做一个事件的Handler直接去调用VM层的方法. 2.控件只有一个Command属性,其它的事件的处理方法没有办法和ViewModel层进行解耦的时候往往也采取上面提到的方法. 如下图所示: 新的做法: 为了实现事件的处理与View层的解耦,我们可以利用WPF提供的附加属性来为需要的事件添加附加行为.附加属性扮演了一个在View层与Model层牵线的角色. 需要下面三个步

vue2.0学习(二)-全局API

vue2.0学习(二)-全局API GitHub源码 https://github.com/sunnyguyan/VueDemo 1.Vue.directive自定义指令 一.什么是全局API? 全局API并不在构造器里,而是先声明全局变量或者直接在Vue上定义一些新功能,Vue内置了一些全局API,比如我们今天要学习的指令Vue.directive.说的简单些就是,在构造器外部用Vue提供给我们的API函数来定义新的功能 二.Vue.directive自定义指令 我们在第一季就学习了内部指令,