WPF 学习笔记《7》——Binding《5》

10. 数据提供程序

(1) XmlDataProvider

XmlDataProvider 允许我们直接将 XML 数据作为数据源,我们将前面章节的例子改成 XML 数据岛试试,注意此时我们已经不需要在代码中定义 Personal、PersonalList 类型。

 1 <Window x:Class="Learn.WPF.Window1"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="Window1">
5 <Window.Resources>
6
7 <XmlDataProvider x:Key="personals" XPath="Personals">
8 <x:XData>
9 <Personals xmlns="">
10 <Personal Name="Tom" Age="15" Sex="Male" />
11 <Personal Name="Mary" Age="11" Sex="Female" />
12 <Personal Name="Jack" Age="12" Sex="Male" />
13 </Personals>
14 </x:XData>
15 </XmlDataProvider>
16
17 </Window.Resources>
18 <Grid>
19 <StackPanel DataContext="{StaticResource personals}">
20 <ListBox x:Name="listbox1" ItemsSource="{Binding XPath=*}">
21 <ListBox.ItemTemplate>
22 <DataTemplate>
23 <StackPanel Orientation="Horizontal">
24 <TextBlock Text="{Binding XPath=@Name}" />
25 <TextBlock>,</TextBlock>
26 <TextBlock Text="{Binding XPath=@Age}" />
27 <TextBlock>,</TextBlock>
28 <TextBlock Text="{Binding XPath=@Sex}" />
29 </StackPanel>
30 </DataTemplate>
31 </ListBox.ItemTemplate>
32 </ListBox>
33 </StackPanel>
34 </Grid>
35 </Window>


在资源中定义 XML 数据岛,注意 "Personals xmlns" 不能省略,另外采用 XPath 进行了绑定操作 (XPath 的语法可参考 MSDN 文档)。除了使用数据岛,我们还以使用 XML 数据文件。

Window1.xaml

 1 <Window x:Class="Learn.WPF.Window1"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:my="clr-namespace:Learn.WPF"
5 Title="Window1">
6 <Window.Resources>
7
8 <XmlDataProvider x:Key="personals" Source="pack://siteOfOrigin:,,,/Personals.xml"
9 XPath="Personals" />
10
11 </Window.Resources>
12 <Grid>
13 <StackPanel DataContext="{StaticResource personals}">
14 <ListBox x:Name="listbox1" ItemsSource="{Binding XPath=*}">
15 <ListBox.ItemTemplate>
16 <DataTemplate>
17 <StackPanel Orientation="Horizontal">
18 <TextBlock Text="{Binding XPath=@Name}" />
19 <TextBlock>,</TextBlock>
20 <TextBlock Text="{Binding XPath=@Age}" />
21 <TextBlock>,</TextBlock>
22 <TextBlock Text="{Binding XPath=@Sex}" />
23 </StackPanel>
24 </DataTemplate>
25 </ListBox.ItemTemplate>
26 </ListBox>
27 </StackPanel>
28 </Grid>
29 </Window>


Personals.xml

1 <?xml version="1.0" encoding="utf-8" ?>
2 <Personals xmlns="">
3 <Personal Name="Tom" Age="15" Sex="Male" />
4 <Personal Name="Mary" Age="11" Sex="Female" />
5 <Personal Name="Jack" Age="12" Sex="Male" />
6 </Personals>


在 Source 属性中指定 XML Uri。

当然,我们也可以在程序代码中通过 XmlDocument 来控制 XML 数据源。

Window1.xaml

 1 <Window x:Class="Learn.WPF.Window1"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="Window1">
5 <Window.Resources>
6
7 <XmlDataProvider x:Key="personals" />
8
9 </Window.Resources>
10 <Grid>
11 <StackPanel DataContext="{StaticResource personals}">
12 <ListBox x:Name="listbox1" ItemsSource="{Binding XPath=*}">
13 <ListBox.ItemTemplate>
14 <DataTemplate>
15 <StackPanel Orientation="Horizontal">
16 <TextBlock Text="{Binding XPath=@Name}" />
17 <TextBlock>,</TextBlock>
18 <TextBlock Text="{Binding XPath=@Age}" />
19 <TextBlock>,</TextBlock>
20 <TextBlock Text="{Binding XPath=@Sex}" />
21 </StackPanel>
22 </DataTemplate>
23 </ListBox.ItemTemplate>
24 </ListBox>
25 </StackPanel>
26 </Grid>
27 </Window>
28
29 Window1.xaml.cs
30
31 public partial class Window1 : Window
32 {
33 public Window1()
34 {
35 InitializeComponent();
36
37 var xml = new XmlDocument();
38 xml.Load("Personals.xml");
39
40 var provider = this.FindResource("personals") as XmlDataProvider;
41 provider.Document = xml;
42 provider.XPath = "Personals";
43 }
44 }


逻辑代码只需修改 XmlDocument 即可自动同步显示到界面上。

protected void ButtonClick(object sender, RoutedEventArgs e)
{
  var provider = this.FindResource("personals") as XmlDataProvider;
  var xml = provider.Document;

  var mary = xml.SelectSingleNode("Personals/Personal[@Name=/"Mary/"]") as XmlElement;
  var age = Convert.ToInt32(mary.Attributes["Age"].Value);

  mary.Attributes["Age"].Value = (++age).ToString();
}
  • 如果设置了 Source 属性,则放弃所有内联 XML 数据;如果设置了 Document 属性,则清除 Source 属性并放弃所有内联 XML 数据。
  • 设置以下属性将隐式导致此 XmlDataProvider 对象刷新:Source、Document、XmlNamespaceManager 和 XPath。
  • 在更改多个导致刷新的属性时,建议使用 DeferRefresh。

(2) ObjectDataProvider

ObjectDataProvider 比我们直接绑定对象有如下三个好处:

  • 可以在 XAML 申明中使用构造参数。
  • 绑定到源对象的方法上。
  • 支持异步数据绑定。

我们先看看构造参数的使用。

Window1.xaml.cs

 1 enum Sex
2 {
3 Male,
4 Female
5 }
6
7 class Personal
8 {
9 public string Name { get; private set; }
10 public int Age { get; private set; }
11 public Sex Sex { get; private set; }
12
13 public Personal(string name, int age, Sex sex)
14 {
15 this.Name = name;
16 this.Age = age;
17 this.Sex = sex;
18 }
19 }
20
21 public partial class Window1 : Window
22 {
23 public Window1()
24 {
25 InitializeComponent();
26 }
27 }


Window1.xaml

 1 <Window x:Class="Learn.WPF.Window1"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:my="clr-namespace:Learn.WPF"
5 xmlns:sys="clr-namespace:System;assembly=mscorlib"
6 Title="Window1">
7 <Window.Resources>
8
9 <ObjectDataProvider x:Key="personal" ObjectType="{x:Type my:Personal}">
10 <ObjectDataProvider.ConstructorParameters>
11 <sys:String>Tom</sys:String>
12 <sys:Int32>15</sys:Int32>
13 <my:Sex>Male</my:Sex>
14 </ObjectDataProvider.ConstructorParameters>
15 </ObjectDataProvider>
16
17 </Window.Resources>
18 <Grid>
19 <StackPanel DataContext="{StaticResource personal}">
20 <Label Content="{Binding Name}" />
21 <Label Content="{Binding Age}" />
22 <Label Content="{Binding Sex}" />
23 </StackPanel>
24 </Grid>
25 </Window>

接下来,我们尝试绑定到一个方法上。
Window1.xaml.cs

 1 class PersonalList : ObservableCollection<Personal>
2 {
3 public PersonalList GetPersonals()
4 {
5 this.Add(new Personal("Tom", 15, Sex.Male));
6 this.Add(new Personal("Mary", 11, Sex.Female));
7 this.Add(new Personal("Jack", 13, Sex.Male));
8
9 return this;
10 }
11 }
12
13 public partial class Window1 : Window
14 {
15 public Window1()
16 {
17 InitializeComponent();
18 }
19 }

Window1.xaml

 1 <Window x:Class="Learn.WPF.Window1"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:my="clr-namespace:Learn.WPF"
5 xmlns:sys="clr-namespace:System;assembly=mscorlib"
6 Title="Window1">
7 <Window.Resources>
8
9 <ObjectDataProvider x:Key="personals" ObjectType="{x:Type my:PersonalList}"
10 MethodName="GetPersonals" />
11
12 </Window.Resources>
13 <Grid>
14 <StackPanel DataContext="{StaticResource personals}">
15 <ListBox x:Name="listbox1" ItemsSource="{Binding}">
16 <ListBox.ItemTemplate>
17 <DataTemplate>
18 <StackPanel Orientation="Horizontal">
19 <TextBlock Text="{Binding Path=Name}" />
20 <TextBlock>,</TextBlock>
21 <TextBlock Text="{Binding Path=Age}" />
22 <TextBlock>,</TextBlock>
23 <TextBlock Text="{Binding Path=Sex}" />
24 </StackPanel>
25 </DataTemplate>
26 </ListBox.ItemTemplate>
27 </ListBox>
28 </StackPanel>
29 </Grid>
30 </Window>

和构造方法参数一样,我们也可以向方法提供参数。

Window1.xaml.cs

 1 class PersonalList : ObservableCollection<Personal>
2 {
3 public IEnumerable<Personal> GetPersonals(int top)
4 {
5 this.Add(new Personal("Tom", 15, Sex.Male));
6 this.Add(new Personal("Mary", 11, Sex.Female));
7 this.Add(new Personal("Jack", 13, Sex.Male));
8
9 return this.Take(top);
10 }
11 }

Window1.xaml

1 <ObjectDataProvider x:Key="personals" ObjectType="{x:Type my:PersonalList}" MethodName="GetPersonals">
2 <ObjectDataProvider.MethodParameters>
3 <sys:Int32>2</sys:Int32>
4 </ObjectDataProvider.MethodParameters>
5 </ObjectDataProvider>
posted @ 2011-08-22 16:51  徐文峰  阅读(280)  评论(0)    收藏  举报