WPF 神话之Binding对象二

    今天我们来探讨的问题,有两个:一是:关于Binding的几个属性问题(Path,Source) 二是:关于几种数据源问题。

    首先来看第一个问题:
 第一个属性:Source:这个数据源有很多种,在接下来我会大家提供几个数据源的例子信息。
 第二个属性:Path,这里将要重点介绍这个属性
 在XAML文件中写Binding的时候。这里的Path是可以不用写的。比如说:
 <GridViewColumn Header="Age"   Width="220" DisplayMemberBinding="{Binding Age}"></GridViewColumn>
 这句话是说Binding一个数据源中的Age属性。这里的Path我是省略掉的。这种写法大家要习惯。

 再来看一种特殊情况。Path采用.来使用的类型。我们来看看这样的一个小例子。
 <Window x:Class="WpfBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"  // 这里我们使用了资源。所以要引用这个命名空间,请注意了。
        Title="MainWindow" Height="800" Width="800">
     <StackPanel>
  <!--定义资源-->
  <StackPanel.Resources>
      <sys:String x:Key="myResource">
   菩提本无树,明镜亦非台。
   本来无一物,何处惹尘埃。
      </sys:String>
  </StackPanel.Resources>
  <!--
  没有Path的Binding.
  1、如果一个数据源本来就是数据,如string,int等。我们可以不用指定Path.
  2、如我们下面的写法
  -->
  <TextBlock x:Name="txtMsg" TextWrapping="Wrap" Text="{Binding Path=.,Source={StaticResource ResourceKey=myResource}}" Margin="5" Background="LightBlue"/>
     </StackPanel>
 </Window>
 这个例子的呈现效果就是。我们看到了资源的信息。会显示出来。
 这里的Binding我们还可以写成这样{Binding .,Source={StaticResource ResourceKey=myResource}} 或者{Binding Source={StaticResource ResourceKey=myResource}}

    接下来我们来探讨第二个问题。关于数据源的问题。
   
    1.DataContext 这个属性是被定义在FrameworkElement类中的,而这个类是WPF控件的一个基类。所以我们WPF控件都有这个属性。
      如果我们在WPF中的某个控件上设置了Path属性,但是没有给定其的Source属性的话。WPF会自动在该控件树上向上查找。把第一个找到的DataContext作为自己的数据源。
   
    2、集合作为数据源的例子。
    代码清单如下:
    XAML:
    <Window x:Class="WpfBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="800" Width="800">
 <StackPanel>
 <!--DataSource的指定这里采用Grid来做布局-->
        <Grid Background="LightBlue">
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition Height="5"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <TextBox x:Name="txtStudentID" BorderBrush="Black" Margin="2"></TextBox>
            <ListBox x:Name="lstStudent" BorderBrush="Black" Height="100" Grid.Row="2">
                <ListBox.ItemTemplate><!--使用模版来进行数据banding-->
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Path=Id}"  Width="100"/>
                            <TextBlock Text="{Binding Path=Name}"  Width="100"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
 </StackPanel>
    </Window>
   
    来看看后台代码
    在后台的初始化中添加这段代码。这里有个Member类。该类里面就两个属性。一个是Id,一个是Name.请各位自己添加一个类就好。
    List<Member> lstMember = new List<Member>(){
                new Member("0001","wy"),
                new Member("0002","love"),
                new Member("0003","hu"),
                new Member("0004","bing"),
                new Member("0001","wy")
            };

            this.lstStudent.ItemsSource = lstMember; // 这里是将我们的数据源给我们的ListBox。关于这点大家应该都很清楚。winform大家应该接触过。
            // this.lstStudent.DisplayMemberPath = "Name";
  
     // 主要来看这段代码。这段代码的意思是
     // 把我们的ListBox作为我们的数据源。目标是我们的文本框。
     // 绑定的对象属性是该数据源中的Id,这里是用的SelectedItem.Id
     // 也就是说选中行的Id.从这里我们就清楚了,这个例子不但进行了数据banding。而且还进行选中行的数据Id同其他控件进行关联
     // 请大家运行下代码看看效果。
            Binding bind = new Binding("SelectedItem.Id") { Source = this.lstStudent };
            this.txtStudentID.SetBinding(TextBox.TextProperty, bind);
  
    3.我们再来看另外几个数据源的情况。
      XAML:
      <Window x:Class="WpfBinding.BindingWin"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="BindingWin" Height="600" Width="600">
    <StackPanel>
        <ListView x:Name="lvStudent" Height="200">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="ID" Width="150" DisplayMemberBinding="{Binding ID}"></GridViewColumn>
                    <GridViewColumn Header="Name" Width="200" DisplayMemberBinding="{Binding StuName}"></GridViewColumn>
                    <GridViewColumn Header="Age"   Width="220" DisplayMemberBinding="{Binding Age}"></GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
        <DockPanel>
            <Button x:Name="btnFromDataTable" Content="从DataTable获取数据" Click="btnFromList_Click" Width="150"></Button>
            <Button x:Name="btnFromXml" Content="从XML中获取数据" Click="btnFromList_Click" Width="150"></Button>
            <Button x:Name="btnObjectDataProvider" Content="ObjectDataProvider" Click="ObjectDataProvider_Click" Width="130"></Button>
        </DockPanel>
 </StackPanel>
       </Window>

       这几个例子会用到一个辅助类
      public class MyStudent {
        public string ID { get; set; }
        public string  StuName { get; set; }
        public int Age { get; set; }

        public MyStudent(string id,string name,int age)
        {
            this.ID = id;
            this.StuName = name;
            this.Age = age;
        }

        public MyStudent()
        {
            // TODO: Complete member initialization
        }
    }
     
      A.来看看DataTable作为数据源的例子
        在按钮btnFromDataTable事件中添加如下代码
     DataTable dt = new DataTable();
     dt.Columns.Add("ID", typeof(string));
     dt.Columns.Add("Name", typeof(string));
     dt.Columns.Add("Age", typeof(int));

     DataRow row1 = dt.NewRow();
     row1["ID"] = "0001";
     row1["Name"] = "Wy";
     row1["Age"] = 25;

     DataRow row2 = dt.NewRow();
     row2["ID"] = "0002";
     row2["Name"] = "Test121";
     row2["Age"] = 24;


     DataRow row3 = dt.NewRow();
     row3["ID"] = "0003";
     row3["Name"] = "Info001";
     row3["Age"] = 25;

     dt.Rows.Add(row1);
     dt.Rows.Add(row2);
     dt.Rows.Add(row3);

     // 记住这里一定要用DefaultView.请大家注意了。大家可以试验下直接把dt赋值过去的效果。
     this.lvStudent.ItemsSource = dt.DefaultView;

     /*
      以上还有一种写法
      this.lvStudent.DataContext = dt;
      this.lvStudent.SetBinding(ListView.ItemSourceProperty,New Binding());
      使用这种方法。Binding会自动找到DefaultView
     */
      B.使用XML文件作为数据源的形式 我这里有个XML文件。我是放在编译目录下的。也就是和我们生成的exe文件在同一个目录。
        <?xml version="1.0" encoding="utf-8"?>
 <StudentList>
  <Student Id="001" Name="Li" Age="25">
  </Student>
  <Student Id="002" Name="Ming" Age="24">
  </Student>
  <Student Id="003" Name="Wang" Age="20">
  </Student>
  <Student Id="004" Name="Hu" Age="25">
  </Student>
  <Student Id="005" Name="Xiao" Age="24">
  </Student>
 </StudentList>

 后台的代码如下:

 // 首先是加载我们的XML文件的内容,然后将这个XDocument文件进行数据的提取
 XDocument doc = XDocument.Load(System.AppDomain.CurrentDomain.BaseDirectory + "Xml.xml");
 this.lvStudent.ItemsSource = from element in doc.Descendants("Student") // 寻找Student节点
     select new MyStudent() {
         ID = element.Attribute("Id").Value,
         StuName =element.Attribute("Name").Value,
         Age = Convert.ToInt32(element.Attribute("Age").Value)
     };

        这里大家可以尝试着试验下。

 还有一种加载XML文件的方式。是这样的。大家看下面一个例子:
 <!--
            加载XML文件的数据
            1、加载xml文件中的数据用Xpath。
            2、加载的是属性值的时候用@Id
            3、如果加载的是子集元素的值就直接用其标签名
        -->
        <ListView x:Name="XmlDataSource" >
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="ID" DisplayMemberBinding="{Binding XPath=@Id}" Width="120"></GridViewColumn>
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding XPath=Name}" Width="120"></GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
        <Button x:Name="BtnShowData" Content="显示数据" Click="BtnShowData_Click"></Button>

 这里很简单。就是一个显示内容的容器。一个按钮。
 这里有点申明。XPath=@Id是说明绑定的是Id这个属性 XPath=Name是说明加载Name节点的内容。这里就是有@和没有@的区别。请大家一定要注意。

 我们来看看XML文件的结构:
 <?xml version="1.0" encoding="utf-8"?>
 <StudentList>
  <Student Id="001">
   <Name>Wang</Name>
   <Age>25</Age>
  </Student>
  <Student Id="002">
   <Name>Yu</Name>
   <Age>24</Age>
  </Student>
  <Student Id="003">
   <Name>Zhang</Name>
   <Age>20</Age>
  </Student>
  <Student Id="004">
   <Name>Ping</Name>
   <Age>25</Age>
  </Student>
  <Student Id="005">
   <Name>Li</Name>
   <Age>24</Age>
  </Student>
 </StudentList>

 我们来看看按钮下面是怎么来加载XML文件并且显示在我们的UI上的。
 这里给出两种写法:

     /* 第一种加载方式
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("MyXml.xml");

            XmlDataProvider xp = new XmlDataProvider();
            xp.Document = xmlDoc;
           
            // 暴露要绑定的数据
            xp.XPath = @"/StudentList/Student";

            this.XmlDataSource.DataContext = xp;
            this.XmlDataSource.SetBinding(ListView.ItemsSourceProperty, new Binding());

     /*第二种加载方式*/
            XmlDataProvider xmlPror = new XmlDataProvider();
           
            xmlPror.Source = new Uri(System.AppDomain.CurrentDomain.BaseDirectory+"MyXml.xml");
            xmlPror.XPath = @"/StudentList/Student";
            this.XmlDataSource.DataContext = xmlPror;
            this.XmlDataSource.SetBinding(ListView.ItemsSourceProperty, new Binding());

  /*
   这里的两种加载。对于XML文件的路径写法是不一样的。这点要注意啊。第一种可以使绝对路径。也可是相对路径。
   而第二种是一种URI的形式。

   可以看出第二种形式是第一种方式的一种简写。
  */

   又到了凌晨了。好了,各位。今天的说明就到这里啊。我们下次再来探讨WPF其他内容。今天就到这里了。各位晚安。美梦。

posted @ 2012-06-27 00:03  HeartDawn  阅读(607)  评论(0编辑  收藏  举报