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>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值