zoukankan      html  css  js  c++  java
  • 数据绑定

    1. 数据绑定(Binding)一般配置

    常用的绑定的目标(Dependency Object & associated Dependency Property,目标单元): 
    内容控件目标:object ContentControl.Content 
    集合控件目标:IEnumerable ItemsControl.ItemSource

    绑定器: 
    Binding ( : BindingBase : MarkupExtension ) 
    Binding binding = new Binding(); 
    binding.ElementName = "WPF控件名称";  / binding.Source = …; 
    binding.Path = new System.Windows.PropertyPath("路径串");

    绑定到源(Object & its Property): 
    代码动态绑定:BindingExtensionBase FrameworkElement.SetBinding(DependencyProperty dp,  BindingBase binding)  (dp = ContentControl.ContentProperty, ItemsControl.ItemsSourceProperty, …) 
                  
    XAML举例:<Label Content=”{Binding … Path=…}”…> ,  <ListBox ItemsSource=”{Binding … Path=…}"> … 
    ({Binding}中单独出现Path时,“Path=”可以省略)

    取消绑定:BindingOperations.ClearBinding(this.Label1, ContentControl.ContentProperty);

    使用DataContext: 
    设置某个单元的FrameworkElement.DataContext属性,为其子单元提供默认的绑定源(Source,ElementName,RelativeSource未设置的Binding),可通过代码和XAML设置。

    设置绑定模式: 
    Default - 采用目标使用的默认方式 
    OneTime - 仅在程序启动或数据源引用或context变动时候更新,但源本身的值发生变化不触发更新 
    OneWay - 仅目标因源而改变(实验中发现,有的时候目标因用户修改,例如TextBox,可能不会再接受源的更改) 
    OneWayToSource - 仅源因目标而改变 
    TwoWay - 双向变化 
    源更新: 
    在上述使用向源反馈更新模式时,设置Binding.UpdateSourceTrigger决定更新的频率: 
    Explicit - 仅在BindingExpression.UpdateSource()时更新,BindingExpression通过这个形式获取:textBox.GettBindingExpression(TextBox.TextProperty); 
    LostFocus - 在包含目标的单元失去焦点时更新; 
    PropertyChanged - 每当目标发生变化时; 
    Default - 根据目标的特性的默认值。

    2. 绑定到Object

    用Binding.Source而不是Binding.ElementName,Binding.Path通常忽略。 
    常用的如画刷设置,以下示例静态对象引用格式: 
    <Button Background=”{Binding Source={x:Static SystemColors.WindowColor}}” …

    另一种应用是绑定到逻辑资源: 
    在资源中定义某个类型的一个资源<名空间别名:类名 x:Key="对象名称"> 
    绑定:Content=”{Binding Source={StaticResource 对象名称}, Path=对象属性}"… 
    其中名空间别名定义: xmlns:别名="clr-namespace:工程代码中的名空间名称[;assembly=库名]"

    3. 绑定到WPF控件

    ElementName设为组件名字符串;Path设为表示值的组件的变量。

    4. 绑定到相对位置

    Binding中的源采用RelativeSource。 
    相对搜索模式: 
    FindAncestor模式从上级搜索源,用AncestorType指定源类型,AncestorLevel指定搜索个数; 
    TemplatedParent模式用于指向当前模板应用的对象; 
    Self通常完成自身两个属性的绑定; 
    PreviousData绑定到数据列表中的前一个数据项。

    5. 绑定到List

    ItemsControl.ItemsSource设置到实现IEnumerable的对象,格式:{Binding Source=主表  Path=xxx},Path用于指定在多层表中指定中间路径,用'.'分隔,CurrentItem指某级的当前项。 
    ItemsControl.IsSynchronizedWithCurrentItem将选定项和CurrentItem同步。 
    ItemsControl.DisplayMemberPath用于指定作为最终显示的字段的属性。 
    ItemsControl.ItemTemplate用于指定数据模板(Data Template)。内容显示由ItemsControls.DisplayMemberPath或ItemsControl.ItemTemplate内部定义(见“数据模板”)两者之一决定。

    内容控件的Content绑定到列表项的某个属性,则需将Path设置到该属性(多层表用'.'分隔,CurrentItem指某级当前项)

    使用ICollectionView检视列表数据(命名空间System.ComponentModel) 
    ICollectionView   o-- 
    DispatcherObject   -- CollectionView – ListCollectionView 
                                         - BindingListCollectionView 
    ICollectionView icv = CollectionViewSource.GetDefaultView(myCollection); 
    (如果是IBindingList则返回IBindingListCollectionView,是IList则返回IListCollectionView) 
    icv可以用于浏览,icv.CurrentItem指向当前项(目前未发现能实现多级表)

    6. 绑定到ADO.NET

    用{Binding Path=xx/yy/zz (Source=tt)}模式。 
    Data Set:首先调用Adapters的Fill将DataSet对象中的DataTable,DataContext可以设到DataSet或其下辖DataTable,在Path中相应调整即可。 
    多层级目标:无当前项指标(CurrentItem),只需表示层级路径即可。 
    关联数据表:将父表设IsSynchronizedWithCurrentItem="True",关联属性表现在Path中,将目标字段表现在DisplayMemberPath,这样关联即显示在界面上。关联设置在VS中导入的XSD文件上进行,设置父子表和相应的关键栏和外部关键键栏。

    7. 绑定到ObjectDataProvider

    将WPF单元内容绑定到一个对象的方法的返回值,主要需要设置ObjectDataProvider.ObjectType到对象类型,ObjectDataProvider.MethodName到方法名称,MethodParameters,ConstructorParameters属性用来指定方法参数和对象构造函数参数。在XAML中格式: 
    在资源(xxx.Resources)中定义: 
    <ObjectDataProvider x:Key=”myDataProvider” ObjectType={x:Type 名空间:类名}" MethodName=”…” /> 
    引用: {Binding Source={StaticResource myDataProvider}} 
    此种方式始终只读,即不允许改变数据源。

    8. 绑定到XML

    在资源(xxx.Resources)中定义: 
    <XmlDataProvider x:Key=”…” Source=”xxx.xml”/> 
    或者: 
    <XmlDataProvider x:Key=”…”> 
    <x:XData> 
       直接嵌入XML数据 
    </x:XData> 
    </XmlDataProvider> 
    引用时类似7将Source指向资源。

    在多层级列表模式下,DataContext=”{Binding …}" 用于定位。一般在全局区(如Grid),DataContext的Binding设置Source,并用XPath过滤掉不需要考虑的高层级。 
    在下一级,DataContext的Binding设置Path=CurrentItem,如果是二级以上,必须设ElementName以指向上一列表控件,而Path=SelectedItem,这样将上一级的选定项设为本级的Context。而ItemsSource的Binding则用XPath进行过滤修正,而最终显示项则取决于ItemsControls.DisplayMemberPath或ItemsControl.ItemTemplate两者之一。对XML中的属性内容在路径中用@propName格式。以下举例说明ItemTemplate的使用: 
    <ListBox.ItemTemplate> 
      <DataTemplate> 
        <TextBlock Text=”{Binding XPath=@propName}” />  
      </DataTemplate> 
    </ListBox.ItemTemplate>

    9. 数据模板(Data Templates)

    上一节已经涉及了数据模板的使用。数据模板用于定制数据的显示。 
    列表控件:设置在ItemsControl.ItemTemplate(DataTemplate类型)上。ItemTemplate顾名思义,对应一个列表项的显示,因此可以通过适当组织将一个列表项对应多个数据字段。 
    内容控件:设置在ContentControl.ContentTemlate。 
    数据模板的类型均为DataTemplate,显然内容也就定义在<DataTemplate></DataTemplate>中,是一个DependencyObject。涉及元素项内容通常用{Binding Path=…}(XML用XPath)绑定。 
    在资源中定义数据模板:类似一般资源,在DataTemplate上标记x:Key,在使用的时候用ItemTemplate="{StaticResource xxx}"引用。

    10. 数据排序(Sorting)

    1. 用CollectionViewSource.GetDefaultView(…)先获取一个ICollectionView(使用命名空间System.ComponentModel) 
    2. 在SortDescriptionCollection ICollectionView.SortDescriptions上调Add方法,添加new SortDescription("字段名称", ListSortDirection.Ascending(升序)) 
    3. 可以继续添加SortDescription,根据添加先后确定排序优先级。

    自定义排序: 
    对于默认生成ListCollectionView(即实现IList,但非IBindingList,如ObservableCollection),通过设置IComparer ListCollectionView.CustomSort属性可以应用自定义排序。IComparer需要实现的方法是:int Compare(object x, object y)

    在XAML中直接定义CollectionViewSource: 
    1. <CollectionViewSource x:Key=’somekey’ (这个Source定义成资源) 
                                         Source=“{Binding xxx}” (绑定到源列表,类似GetDefaultView的参数,XML可设XPath) 
    2. 随后可以定义<CollectionViewSource.SortDescriptions>或以下的<CollectionViewSource.GroupDescriptions>中的内容,类似于上述Add方法。 
    3. 后续依赖于源列表和这个基于CollectionViewSource的分组或排序定义的单元可以直接将Binding的源定义到上面的Key。

    11. 数据编组(Grouping)

    编组即排序加区分。 
    1. …获取一个ICollectionView 
    2. 在ObservableCollection<GroupDescription> ICollectionView.GroupDescriptions上调Add方法,添加new PropertyGroupDescription("字段名"[, CustomGrouper]),其中PropertyGroupDescription 继承自GroupDescription,自定义编组需CustomGrouper实现IValueConverter接口。 
    3. 设置列表控件的组的显示特性ItemsControl.GroupStyle(如<ListBox.GroupStyle>)。GroupStyle有五个主要属性,常用: 
    HeaderTemplate,它是一个控制组表头的显示的DataTemplate,其{Binding Path=xxx},实际绑定到PropertyGroupDescription构造函数第一个参数指定的属性(在某些情况下可忽略为{Binding}); 
    Panel,它是一个设置列表元素布局的模板,ItemsPanelTemplate类型,注意这个Panel是以Group为单位进行布局的,而不是直接针对Item; 
    ContainerStyle,Style类型,用于指定每个具体的编组元素(TargetType为GroupItem)的样式。有关Template使用详见后续章节。

    DispatcherObject - FrameworkTemplate – DataTemplate 
                                         - ItemsPanelTemplate 
    自定义编组: 
    IValueConverter需要实现object Convert(object value, Type targetType, object parameter, Sytem.Globalization.CultureInfo culture)和同参数的ConvertBack函数,在编组中ConvertBack函数不被调用。Convert方法完成PropertyGroupDescription指定的数据转换,转换输出的内容被作为最终分组的依据,通常可以进行字符串格式化操作和一些映射等(详见13节)。

    12. 数据过滤(Filtering)

    根据Predicate委托类型:bool Predigate<T>(T obj),实现一个过滤器,设置ICollectionView.Filter属性到这个方法上,只有通过过滤(返回true)的才会包含进来并显示。

    在使用ADO.NET或使用BindingListCollectionView时,则不能用上述过滤方法。而要用BindingListCollectionView.CustomFilter字符串,通常形如"字段名=='值'"。具体格式同DataColumn.Expression,非WPF关注内容,参见相关文档。

    13. 数据转换

    如11所述,IValueConverer数据转换可用于编组,需要实现的方法也已介绍。 
    通常定义实现IValueConverter的类之前需要标志[ValueConversion(typeof(输入类型), typeof(输出类型)]修饰,一般不需要实现ConvertBack方法的实际功能。 
    在XAML中使用转换器: 
    1. 用xmlns引用必要的名空间。 
    2. 在资源如<Window.Resources>中实例化一个转换器(用x:Key标识)。 
    3. 在用到数据绑定Binding的地方,设置Binding的Converter属性引用资源中这个转换器。

    字符串格式化(详见相关文档)。常用: 
    数值到货币:num.ToString("C"); (这个转换基于当前线程的文化信息) 
    日期格式化:d-短日期格式,D-长日期格式,f-长日期短时间格式,F-长日期长时间格式,G-一般格式,M-日月,s-ISO标准格式

    提取对象。例如: 
    从URI字符串提取图像。

    个性化列表项: 
    例如设置转换器将输入日期转换到一个画刷,将转换器设置到列表项DataTemplate中单元(如Label)的Foreground的Binding上,就实现不同日期的不同颜色显示。

    转换器的本地化: 
    Convert方法中有一个文化信息参数culture,据此可以对转换过程做适当的处理,例如调用相应的翻译器等。

    多参数转换: 
    实现接口IMultiValueConverter,相应的转换方法: 
    object Convert(object[] values, Type targetType, 后同); 
    object[] ConvertBack(object value, Type[] targetTypes, 后同); 
    多参数转换也是在XAML的资源中实例化转换器,然后在MuliBinding中使用: 
    <MultiBinding Converter="资源"> 
      <Binding Path=xxx1 /> 
      <Binding Path=xxx2 /> 
    </MultiBinding>

    14. 数据验证(Validation)

    数据验证在界面上指示数据的有效性。 
    它通过Collection<ValidationRule> Binding.ValidationRules包含的验证规则实现,验证过程根据定义依次执行: 
    <Binding.ValidationRules> 
      <ns:ValidationRule派生类1/> 
      <ns:ValidationRule派生类2/> 
      .. 
    </Binding.VaidationRules>

    派生类必须重载:ValidationResult Validate(object value, CultureInfo ci);  
    ValidationResult构造:ValidationResult(bool isvalid, object 错误内容对象(通常是消息串,无错误设null));

    当验证发生错误时会发生(不会触发任何异常): 
    1. 相应的单元周围出现红色框; 
    2. 单元上的关联属性Validation.HasErrorProperty变为True; 
    3. 单元上的关联属性Validation.ErrorsProperty中添加相应的ValidationError对象; 
    4. 如果相应Binding.NotifyOnValidationError设为True,则接力事件Validation.ErrorEvent被触发; 
    5. 相应的数据源不会更新到错误值。

    通过添加ExceptionValidationRule到ValidationRules中,可以使Binding中的任何异常都转变为上报验证错误。

    处理验证错误: 
    Validation.ErrorEvent的事件参数是ValidationErrorEventArgs,包含两个属性: 
    Action: 触发后首先是ValidationErrorEventAction.Added,当再次验证的时会首先清除前次的错误,再次触发事件,并使Action参数为ValidationErrorEventAction.Removed; 
    Error: 包含以下信息: 
    - object ErrorContent:  ValidationRule对象返回ValidationResult中设置的对象 
    - Exception Exception: 导致验证错误的异常(使用上述ExceptionValidationRule) 
    - BindingExpression BindingInError: 获得导致验证错误的Binding对应的BindingExpression,通过BindingExpression.ParentBinding可以得到Binding。 
    - RuleInError:获得对应的验证规则。

    15. 数据变更通知(Data Change Notification)

    自定义的数据源的数据更新往往通过: 
    1. 单独的数据对象,实现INotifyPropertyChanged接口实现, 
    在参数设置set过程中,调用PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("被改变的属性名"); 
    2. 集合数据对象,继承ObservableCollection,可直接依赖其内建的变更通知体系,则列表内容增删变更都会通知。一般形式: 
    class MyItems : System.Collections.ObjectModel.ObservableCollection<MyItem> { … } 
    集合元素的对象必须实现INotifyPropertyChanged以完成自身的变更通知。

    当显式设置Binding.NotifyOnSourceUpdated=”True”时,数据变更会触发接力事件Binding.SourceUpdatedEvent。

  • 相关阅读:
    Python机器学习算法 — KNN分类
    八大排序算法(Python)
    探究为何rem在chrome浏览器上计算出错
    HTML邮件制作规范
    怎样用sourceTree将自己本地的项目上传到github网站上
    图片裁切插件jCrop的使用心得(四)
    图片裁切插件jCrop的使用心得(三)
    图片裁切插件jCrop的使用心得(二)
    图片裁切插件jCrop的使用心得(一)
    几个css的小知识点(一)
  • 原文地址:https://www.cnblogs.com/sjqq/p/6626362.html
Copyright © 2011-2022 走看看