zoukankan      html  css  js  c++  java
  • WPF学习(4) – WPF中的数据绑定

    1. 绑定对象

    数据绑定是通过System.Windows.Data.Binding对象来实现,它能够将2个属性绑定在一起,在接下来的应用程序生命周期中让绑定来负责所有的同步工作。

    1.1 在代码中实现

    绑定代码

    Binding binding = new Binding();

    //设置源对象

    binding.Source = treeview;

    //设置源属性

    binding.Path = new PropertyPath("SelectedItem.Header");

    //添加到目标属性

    currentFolder.SetBinding(TextBlock.TextProperty, binding);

    解除绑定代码

    BindingOperation.ClearBinding(currentFolder, TextBlock.TextProperty); //清除currentFolder的TextBlock

    BindingOperation.ClearAllBindings(currentFolder)  //清除所有和currentFolder有关的绑定

    1.2 在XAML中使用绑定

    <TextBlock x:Name="currentFolder" DockPanle.Dock="Top" Text="{Binding SelectedItem.Header, ElementName=treeview}"/>

    1.3 与普通的.NET属性绑定

    可以绑定.NET的对象的普通属性,如:

    <Label x:Name="numItemsLabel" Content="{Binding Source={StaticResource photoes}, Path=Count}" DockPanel.Dock="Bottom"/>

    虽然可以用,但是有弊端。因为普通的.NET对象属性和WPF中的依赖属性相比, 没有自动的变更机制支持。

    为了让目标和源属性保持同步,源对象必须实现以下技术中的一种:

    • 实现System.ComponentModel.INotifyPropertyChanged接口,该接口有一个PropertyChanged事件。
    • 实现XXXChanged事件,其中XXX是值发生改变的属性的名称。

    常用的是第一种,WPF对其进行了优化。

    1.4 绑定到整个对象

    绑定中的Path是可选的,你可以绑定整个对象。

    这种绑定方式对于那些能够充分利用对象的元素,比如ListBox, 是非常有用的。

    1.5 绑定到集合

    浅数据绑定

    例如,绑定一个对象到ListBox, 但是不能绑定到Items属性, 因为Items不是依赖属性。

    所以我们使用ListBox.ItemSource属性

    改进显示方式

    默认绑定集合的显示方式,用ToString呈现,并不能让人接受。可以使用DisplayMemberPath属性和ItemSource配合。

    <ListBox x:Name="pictureBox" DisplayMemberPath="Name" ItemSoruce="{Binding Source={StaticResource photos}}"

    </ListBox>

    管理选中项

    <ListBox IsSynchronizedWithCurrentItem="True" DisplayMemeberPath="Name" ItemSource="{Binding Source={StaticResource photos}}"></ListBox>

    <ListBox IsSynchronizedWithCurrentItem="True" DisplayMemeberPath="DateTime" ItemSource="{Binding Source={StaticResource photos}}"></ListBox>

    <ListBox IsSynchronizedWithCurrentItem="True" DisplayMemeberPath="Size" ItemSource="{Binding Source={StaticResource photos}}"></ListBox>

    因为设置了IsSynchronizedWithCurrentItem为True, 所有指向同一个源的的控件,改变任何一个控件的选中项都会同时改变其他两个控件。

    1.6 使用DataContext共享数据源

    使用DataContext指定共享数据源,下面的数据绑定,就可以简化。

    <StackPanel x:Name="parent" DataContext="{StaticResource photos}">

    <ListBox IsSynchronizedWithCurrentItem="True" DisplayMemeberPath="Name" ItemSource="{Binding}"></ListBox>

    <ListBox IsSynchronizedWithCurrentItem="True" DisplayMemeberPath="DateTime" ItemSource="{Binding}"></ListBox>

    <ListBox IsSynchronizedWithCurrentItem="True" DisplayMemeberPath="Size" ItemSource="{Binding}"></ListBox>

    </StackPanel>

    2. 控制呈现

    WPF中使用数据模板和值转换器来控制控件的呈现

    2.1 使用数据模板

    很多控件都提供一些属性可以用来添加数据模板。例如ContentControl的ContentTemplate属性, ItemControl的ItemTemplate属性,HeaderedContentControl的HeaderTemplate属性。

    <ListBox x:Name="pictureBox" ItemSource="{Binding Source={StaticResource photos}}">

    <ListBox.ItemTemplate>

         <DataTemplate>

               <Image Source="{Binding Path=FullPath}" Height="35"/>

         <DataTemplate>

    </ListBox.ItemTemplate>

    </ListBox>

    2.2 使用值转换器

    对不兼容的数据类型做桥接

    在数据绑定的时候,我们常常不能够直接使用,而需要转换。

    比如实现一个bug记录软件,当bug数目超过600的时候,显示bug的数字背景要用红色。颜色的属性如何和bug数目绑定呢?

    可以用值转换器来实现

    <Label Background=“Binding Path=Count,Converter={StaticResource myConverter}, Source={StaticResource photos}”/>

    实现的值转换器必须实现IValueConverter接口。IValueConverter接口有两个简单的方法——Convert和ConvertBack.

    自定义数据显示

    有时候虽然不存在数据类型不兼容的情况,但是我们可以使用值转换器来达到让结果更加易读的目的。

    3. 定制一个集合的视图

    事实上,无论何时绑定到一个集合(任何实现了IEnumerable的类), 都会有一个默认的视图隐式地被插入到源对象和目标对象之间。

    该视图(它是一个实现了ICollectionView接口的对象)存储着当前项的信息,但是它也支持排序、分组、过滤和项导航。

    3.1 排序

    ICollectionView有一个SortDescriptions属性提供了一种方式来控制视图项如何进行排序。

    //获取默认视图

    ICollectionView view = CollectionViewSource.GetDefaultView(this.FindResource("photos"));

    //清空以后的排序

    view.SortDescriptions.Clear();

    //添加排序

    view.SortDescriptions.Add(new SortDescription('Name', ListSortDirection.Ascending));

    3.2 分组

    ICollectionView有一个GroupDescription属性,用它可以把源集合的项放入组和子组中。

    3.3 过滤

    属性Filter是一个委托,返回bool类型。

    3.4 导航

    view支持导航数据的能力,提供了如下这些方法和属性

    IsCurrentBeforeFirst, IsCurrentAfterLast

    MoveCurrentToPrevious(), MoveCurrentToLast() 等

    3.5 使用其他视图

    可以显式手动创建视图,而不是使用默认的视图。 下面是用CollectionViewSource创建的一个复杂的视图。

    <Window.Resources>

        <local:Photos x:Key="photos"/>

        <CollectionViewSource x:Key="ViewSource" Source="{StaticResource photos}" Filter="viewSource_Filter" Source="{StaticResource photos}">

        <CollectionViewSource.SortDescriptions>

                <componentModel:SortDescription PropertyName="DateTime" Direction="Descending"/>

        </CollectionViewSource.SortDescriptions>

        <CollectionViewSource.GroupDescriptions>

                <PoropertyGroupDescription PropertyName="DateTime"/>

        </CollectionViewSource.GroupDescriptions>

    </WIndow.Resources>

    4. 数据提供程序

    源对象可以是任意的.NET对象,所以你有足够的代码来执行任何数据绑定。

    所以我们只要实现一个合适的.NET对象,可以提供正确的属性集合和通知机制,就可以更加方便的构造自己的数据源。

    为了方便,WPF提供了2个类XamlDataProvider和ObjectDataProvider

    4.1 XMLDataProvider

    一个例子

    <Window.Resource>

         <XmlDataProvider x:Key="dataProvider" XPath="GameStats">

                <x:XData>

                 ...................

                </x:XData>

         </XmlDataProvider>

    </Window.Resource>

    <ListBox ItemsSource="{Binding Source={StaticResource dataProvider}, XPath=GameStat/HighScore}"

    这里dataProvider是一个Windows Resource的key, 这个资源是一段xml文本, XPath指出了数据绑定的节点路径。

    4.2 ObjectDataProvider

    我们已经实现了使用.NET对象作为绑定的数据源了,那么使用ObjectDataProvider的意义在哪里呢?

    它可以实现:

    • 声明式地使用带参数的构造函数实现实例化源对象。
    • 绑定到源对象的一种方法。
    • 有更多的选项来做异步数据绑定。

    在XAML中使用带参数的构造函数

    <ObjectDataProvider x:Key="dataProvider" ObjectType="{x:Type local:Photos}">

    <ObjectDataProvider.ConstructorParameters>

         <sys:Int32>23</sys:Int32>

    </ObjectDataProvider.ConstructorParameters>

    </OjbectDataProvider>

    ObjectProvider可以是一个方法

    <ObjectDataProvider x:Key="dataProvider" OjbectType=“{x:Type local:Photos}" MethodName="GetFolderName"/>

    5. 高级主题

    5.1 自定义Binding的数据流

    可以通过设置Binding的Mode属性来改变绑定的数据流。

    Mode可以是BindingMode枚举值:

    • OneWay, 当源改变时,目标会被更新。
    • TwoWay, 源或目标改变,都会导致另一方一起被更新。
    • OneWayToSoruce, 和OneWay相反,当目标改变时,源都会被更新。
    • OneTime, 和OneWay一样工作,但源的改变不会被反映到目标上。目标会保留Binding初始化时源的一个快照。

    TwoWay绑定适合于数据绑定表单, 因为在表单中你可能会有一些运行用户修改数据的TextBox, 且这些TextBox已经被填入了数据。

    事实上,虽然大多数依赖属性默认都是OneWay绑定,但像TextBox.Text这样的依赖属性是TwoWay绑定的。

    5.2 向绑定添加验证规则

    我们可以在绑定的时候,添加验证规则。

    验证规则类需要继承ValidationRule, 重写方法ValidationResult

    <TextBox>

         <TextBox.Text>

               <Binding ...>

                    <Binding.ValidationRules>

                           <local:JpgValicationRule/>

                    </Binding.ValidationRules>

               </Binding>

         </TextBox.Text>

    </TextBox>

  • 相关阅读:
    Attributes in C#
    asp.net C# 时间格式大全
    UVA 10518 How Many Calls?
    UVA 10303 How Many Trees?
    UVA 991 Safe Salutations
    UVA 10862 Connect the Cable Wires
    UVA 10417 Gift Exchanging
    UVA 10229 Modular Fibonacci
    UVA 10079 Pizza Cutting
    UVA 10334 Ray Through Glasses
  • 原文地址:https://www.cnblogs.com/JustRun1983/p/2647249.html
Copyright © 2011-2022 走看看