《深入浅出WPF》学习笔记之深入浅出话Binding

Binding作为数据的桥梁,它的两端分别是Binding的源(Source)和目标(Target),用来把Source中的数据送到Target中,并把在Target中的改变返回到Source。一般情况,Binding的源是逻辑层的对象,目标是UI层的控件对象。

Binding的基本使用方法

如果想让作为数据源的对象在发生更改时自动显示到界面上,数据源的对象需要实现INotifyPropertyChanged接口。设置绑定时需要指定绑定到数据源的哪个属性,这个属性称为Binding的路径Path。通过绑定方法把Binding对象关联到目标上,同时指定把数据送达目标的哪个属性,目标的Binding属性必须为依赖属性。示例代码:

            Binding binding = new Binding();
            binding.Source = DateTime.Now;
            binding.Path = new PropertyPath("Year");

            BindingOperations.SetBinding(txtBlock, TextBlock.TextProperty, binding);
            //txtBlock.SetBinding(TextBlock.TextDecorationsProperty, binding);

设置绑定时也可以通过FrameworkElement的SetBinding方法实现。

Binding的数据源

如果想让数据源对象更改时自动通知Binding更新UI,则需要源对象实现INotifyPropertyChanged接口。除了普通对象作为数据源外,还可以把其他控件、集合、XML数据等作为数据源。

通过标记扩展把一个控件的属性关联到另一个控件的属性上,示例代码:

        <TextBox Text="{Binding Path=Value,ElementName=slider}"></TextBox>
        <Slider x:Name="slider"></Slider>

控制Binding数据流向的属性是Mode,类型为BindingMode枚举,TwoWay:双向流动,OneWay:由源流向目标,OneTime:只读取一次,OneWayToSource:从目标流向源,Default:根据目标的实际情况来确定,若目标是可编辑的则为TwoWay,若目标为只读的,则为OneWay。可以通过更改Binding的UpdateSourceTrigger属性来指定Target更新Source的时机。还可以为目标元素添加监听Binding的附加事件SourceUpdated和TargetUpdated来监听源和目标的更新。

当为Binding指定数据源的Path时,可以使用"."操作符,如Property.property,甚至可以使用索引器如Property.[1]或Property[1]。如果Binding的源是一个集合,如果想获取第一个元素作为Binding的Path,则使用“/”获取第一个元素,如果获取的元素仍是一个集合,则可以继续使用“/”获取集合的第一个元素,示例代码:

        public class Student
        {
            public String Name { get; set; }
            public List<Book> Books { get; set; }
        }
        public class Book
        {
            public String BookName { get; set; }
        }           

            List<Student> students = new List<Student>();
            students.Add(new Student() { Name = "Jeff", Books = new List<Book>() { new Book() { BookName = "C#" }, new Book() { BookName = "Java" } } });
            students.Add(new Student() { Name = "Sam", Books = new List<Book>() { new Book() { BookName = "Game" }, new Book() { BookName = "Hobbit" } } });

            txtBlock1.SetBinding(TextBlock.TextProperty, new Binding("/Name") { Source = students });//Jeff
            txtBlock2.SetBinding(TextBlock.TextProperty, new Binding("/Books/BookName") { Source = students });//C#

如果数据源本身是基础类型(如String、int等),则无需指定Path,在C#代码中使用“.”,在XAML语法中可以不指定Path属性或也可以指定“.”。

为Binding指定源的几种方法

普通的CLR对象作为数据源,集合对象包括数组、List、ObservableCollection<T>,ADO.NET对象,XmlDataProvider,依赖对象,控件的DataContext属性,通过Binding对象的ElementName属性指定Source,通过Binding的RelativeSource属性指定Source,把ObjectDataProvider对象指定为Source,把使用LINQ检索得到的数据作为数据源。

使用DataContext作为数据源时,绑定时可以实现自动向父级控件查找数据源,直到找到包含DataContext的控件,自动查找过程是通过依赖属性实现的,DataContext为依赖属性,当控件未指定DataContext时会自动继承父级的属性。

为ItemsControl控件绑定数据源时只需把数据源对象赋值到ItemsSource属性,数据源对象应为集合对象,控件会自动为集合中的元素设置Binding。为了使集合中元素个数更改时ItemsControl对象能得到通知,集合对象必须实现IObservable接口。注意如果想实现在集合中的元素属性更改时能通知到Binding对象,集合元素必须实现INotifyPropertyChanged接口。ObservableCollection<T>为实现了IObservable的集合。

使用ADO.Net的DataTable对象作为ItemsControl的数据源时,把DataTable的DefaultView属性赋值给ItemsSource。通常用ListView来显示表格数据,同时需要设置ListView的View属性为GridView,GridView的内容为GridViewColumn,GridViewColumn的DisplayMemberBinding属性为一个Binding对象,通过设置该对象来指定该列与Source对象的哪个属性关联,这与ListBox不同。

如果需要把XML数据作为Binding的源,需要使用XMLDataProvider对象,设置Binding的路径时需要使用Xpath设置,使用@符号时表示获取XML元素的Attribute,不使用时表示获取元素的子级元素。

ObjectDataProvider用来包装一个以方法暴露数据的对象,通过设置ObjectInstance指定被包装的对象,MethodName指定要调用的方法,MethodParameters指定方法的参数。当把ObjectDataProvider绑定到Target上时不需要设置Binding的Path属性,ObjectDataProvider本身就是数据。

使用Binding的RelativeSource用来指定相对数据源,通过RelativeSource类的属性设置控制Binding搜索Source的范围和方式。Mode属性的类型是RelativeSourceMode,取值为PreviousData、TemplatedParent、Self、FindAncestor。可以通过静态属性PreviousData、TemplatedParent和Self快速获取RelativeSource的实例。

Binding的数据校验

Binding的ValidationRules属性用来控制数据校验,可以同时设置多个校验对象。每个校验规则为ValidationRule对象,ValidationRule是抽象类,使用时需要实现自己的派生类。Binding的校验默认只校验来自Target的数据,即默认Source中的数据永远是正确的,如果想在Source更新时也进行校验,需要设置ValidationRule的属性ValidatesOnTargetUpdated为True,这样在Source的数据更新时也会调用校验方法。如果想在校验错误时触发事件,需要设置Binding的NotifyOnValidationError属性为true,并在Binding的Target上或其父级上监听Validation的Error附加事件。示例代码:

        this.textBlock1.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(ValidationError));
        private void ValidationError(Object sender,RoutedEventArgs e)
        {
            if(Validation.GetErrors(textBlock1).Count>0)
            {
                textBlock1.ToolTip = Validation.GetErrors(textBlock1)[0].ErrorContent.ToString();
            }
        }

Binding的数据转换

当Binding的Source的Path属性的值类型与Target的属性值类型不一致时,要进行类型转换。如果是简单类型如String,Double等,在WPF中已经内置转换方法,如果是其他复杂类型,需要自己编写转换类。实现IValueConverter接口,该接口定义两个方法,当数据从Binding的Source流向Target时Convert方法被调用,反之ConvertBack方法被调用。Binding的Mode影响着方法被调用的情况,如果Mode为TwoWay,两个方法都有可能被调用,如果Mode为OneWay,则只有Convert被调用。创建绑定时设置Binding的Converter属性指定Binding要使用的转换器。

MultiBinding

当UI中需要显示的信息由不只一个数据来源决定时,这时候需要使用多路绑定。MultiBinding与Binding一样以BindingBase为基类,MultiBinding有一个类型为BindingBase集合的属性Bindings,通过该属性把多个Binding汇集到一起。汇集起来的Binding共同决定去往MultiBinding的Target的数据。MultiBinding对于添加子集Binding的顺序是敏感的,添加顺序决定传到Converter中的数据的顺序。MultiBinding的Converter实现的是IMultiValueConverter接口,MultiBinding貌似必须要指定自定义的Converter。

时间: 2024-10-23 18:12:30

《深入浅出WPF》学习笔记之深入浅出话Binding的相关文章

《深入浅出WPF》笔记——绘画与动画

<深入浅出WPF>笔记——绘画与动画 本篇将记录一下如何在WPF中绘画和设计动画,这方面一直都不是VS的强项,然而它有一套利器Blend:这方面也不是我的优势,幸好我有博客园,能记录一下学习的过程.在本记录中,为了更好的理解绘画与动画,多数的例子还是在VS里面敲出来的.好了,不废话了,现在开始. 一.WPF绘画 1.1基本图形 在WPF中可以绘制矢量图,不会随窗口或图型的放大或缩小出现锯齿或变形,除此之外,XAML绘制出来的图有个好处就是便于修改,当图不符合要求的时间,通常改某些属性就可以完成

WPF学习笔记4&mdash;&mdash;Layout之2

下面简单介绍常见的面板. 一.Grid 1.Grid关于调整行列距离有三种方法:绝对大小,自动大小,比例大小.如下: <ColumnDefinition Width="100"></ColumnDefinition> <ColumnDefinition Width="Auto"></ColumnDefinition> <ColumnDefinition Width="*"></Co

WPF学习笔记2&mdash;&mdash;XAML之2

三.事件处理程序与代码隐藏 例如,为一个Page添加一个Button控件,并为该Button添加事件名称Button_Click: <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="ExampleNamespace.ExampleP

WPF学习笔记系列之一 (布局详情)

布局:StackPanel  栈布局:控件不会拐弯且多出的不再显示.DockPanel   停靠布局 吸在上边下边或左右.WrapPanel    环绕布局   一行控件会拐弯Canvas  进行基于坐标的布局 Grid中若不指定Grid.Row属性及Grid.Column则默认为:0行,0列.RowDefinitions ColumnDefinitions ShowGridLines=true <ColumnDefinition Width="100"></Colu

【WPF学习笔记】之 System.Exception 对象名 &#39;XXXX&#39; 无效。

我在运行vs时候发现项目报错,如下图: 报Exception错误,对象名"XXXXXX"无效. 经过调查得知,因为连接数据库的库名写错了,如下: 对应正确数据库的库名: 把库名改正确,问题就解决了. [WPF学习笔记]之 System.Exception 对象名 'XXXX' 无效.

WPF学习09:数据绑定之 Binding to List Data

从WPF学习03:Element Binding我们可以实现控件属性与控件属性的绑定. 从WPF学习07:MVVM 预备知识之数据绑定 我们可以实现控件属性与自定义对象属性的绑定. 而以上两个功能在实际应用中还是不够的,我们经常需要将列表数据与控件属性进行绑定. 例子 ListBox切换人物,下面两个文本框跟随切换,很常用的功能. XAML代码: <Window x:Class="DataTemplate.MainWindow" xmlns="http://schema

《深入浅出WPF》学习笔记之深入浅出话事件

WPF的事件为路由事件,路由的环境为UI组件树(Visual Tree),Visual Tree由控件和控件的组成元素组成,事件可以在控件内部传递并处理.另一个树为Logical Tree,只包含布局控件和其他控件而不包括控件的组成元素.因此路由事件沿着Visual Tree传递. 传统.Net开发中的直接事件模型的缺点 事件拥有者和响应者必须建立订阅关系,如果想让事件向外层控件传递必须手动编写事件响应链,即每个控件都要订阅事件并向其他控件再次传递该事件. 路由事件 与依赖属性类似,每个路由事件

《深入浅出WPF》学习笔记之深入浅出话资源

资源的使用 每个继承自FrameworkElement的类都有一个Resources的字段属性,用来存放自己的资源对象,Resources的类型为SourceDictionary,可以指定Source属性为一个文件路径而引用整个文件的资源. <Window.Resources> <sys:String x:Key="title">资源示例</sys:String> </Window.Resources> //引用外部资源文件 <Wi

《深入浅出WPF》笔记一

1.项目模板 Visual Studio自动配置编译器参数,并准备好一套基本的源代码. 2.App.xaml/App.xaml.cs 声明程序的进程,并指定程序的主窗体. 3.Attribute和Property Attribute:特征,属于编程语言语法层面,是为了区分同类的不同语法元素. Property:属性,属于面向对象理论范畴,指的是类中用来表示事物状态的成员. Attribute只是用来影响类在程序中的用法,Property则对应抽象对象本身的性状. 使用能够进行面向对象编程的语言,