WPF Binding学习(四) 绑定各种数据源

1.集合作为数据源

首先我们先创建一个模型类

 public class Student
    {
        public int ID { get; set; }
        public String Name { get; set; }
    }

然后我们创建我们的页面布局

 <StackPanel Width="300" Height="300" HorizontalAlignment="Left">
        <ListView Name="listView1">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="编号" DisplayMemberBinding="{Binding ID}" Width="100"></GridViewColumn>
                    <GridViewColumn Header="姓名" DisplayMemberBinding="{Binding Name}" Width="100"></GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>

    </StackPanel>

在这里我们使用了ListView控件和GridView控件来显示数据,这两个控件从表面来看应该属于同一级别的控件。实际上并非如此!ListView是ListBox的派生类,而GridView是ViewBase的派生类,ListView中的View是一个ViewBase对象,所以,GridView可以做为ListView的View来使用而不能当作独立的控件来使用。这里使用理念是组合模式,即ListView由一个View,但是至于是GridVIew还是其它类型的View,由程序员自己选择。其次,GridView的内容属性是Columns,这个属性是GridViewColumnCollection类型对象。因为XAML支持对内容属性的简写,可以省略<GridView.Columns>这层标签,直接在GridView内部定义<GridViewColumn>对象,GridViewColumn中最重要的一个属性是DisplayBinding(类型是BindingBase),使用这个属性可以指定这一列使用什么样的Binding去关联数据-----这与ListBox有些不同,ListBox使用的是DisplayMemberPath属性(类型是String)。如果想用更复杂的结构来表示这一标题或数据,则可为GridViewColumn设置Head Template和Cell Template,它们的类型都是DataTemplate

接下来下后台代码

 IList<Student> list = new ObservableCollection<Student>()
            {
                new Student(){ID=1,Name="狗娃"},
                  new Student(){ID=2,Name="狗剩"},
                    new Student(){ID=3,Name="铁蛋"}
            };
            this.listView1.ItemsSource = list;
          

只需在构造函数中创建对象并绑定到ListView上即可,然后运行就可以看到已经绑定完毕

接下来看一下ObservableCollection这个集合,我们可以看到在这里使用的是ObservableCollection集合而并非平常的List集合,那么为什么呢,因为ObservableCollection集合实现了INotifyCollectionChanged接口,也就是可以双向绑定。

2.ADO.NET中DataTable对象做为数据源

在wpf中,是允许将DataTable直接做为Binding的数据源的,下面以一个例子做为参考

控件还可以用上面的控件,只需该数据源即可

首先先创建一个用于创建DataTable的方法

   public DataTable CreateDt()
        {
            DataTable dt = new DataTable();
            DataColumn[] dc = new DataColumn[]
            {
                new DataColumn("ID"),
                 new DataColumn(){ColumnName="Name"}
            };
            dt.Columns.AddRange(dc);
            return dt;
        }

然后再构造函数中创建DataTable,赋予值并绑定即可

  DataTable dt = CreateDt();
            DataRow dr = dt.NewRow();
            dr[0] = 1;
            dr[1] = "狗娃";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 2;
            dr[1] = "狗剩";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 1;
            dr[1] = "铁蛋";
            dt.Rows.Add(dr);
            //将数据源设置为Dt的视图
            this.listView1.ItemsSource = dt.DefaultView;

3.使用XML数据作为数据源

WPF提供了两套处理XML的类库:

  1.符合DOM(Document Object Model 文档对象模式)标准类库:XmlDocument.XmlElement,XmlNode等类,这套类型特点中规中矩,功能强大,但也背负了太多的XML传统和复杂

  2.以LINQ(Language-Intergrated Query 语言集成查询)为基础的类库,包括:XDocument,XElement,XNode,XAttribute等类,这套类库特点是可以通过LINQ进行查询和操作,方便快捷

首先使用第一种方案

    先创建一个XML文件

<?xml version="1.0" encoding="utf-8" ?>
<StudentList>
    <Student id="1">
        <Name>狗娃</Name>
    </Student>
    <Student id="2">
        <Name>狗剩</Name>
    </Student>
    <Student id="3">
        <Name>铁蛋</Name>
    </Student>
</StudentList>

然后创建XAML

 <StackPanel Width="300" Name="stackPanel1">
        <ListView Name="listView1">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="编号" DisplayMemberBinding="{Binding [email protected]}">

                    </GridViewColumn>
                    <GridViewColumn Header="姓名" DisplayMemberBinding="{Binding XPath=Name}">

                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </StackPanel>

注意:XML绑定不是使用Path,而是XPath

 XmlDocument doc = new XmlDocument();
            doc.Load(@"C:\资料\f盘\代码\c#\WPF\TreeView\TestSource\Students.xml");
            //通过XmlDataProvider进行绑定数据
            XmlDataProvider dp = new XmlDataProvider();
            dp.Document = doc;
            dp.XPath = @"StudentList/Student";
            this.listView1.SetBinding(ListView.ItemsSourceProperty, new Binding() { Source=dp});

绑定XMl使用到了XmlDataProvider,这个类是将XMl做为数据源源的一种快捷方式.XmlDataPrivider有个Source属性,可以使用它直接指定XML文档地址(无论XML文档是存储在本地还是网络位置),所以也可以这么写

 XmlDataProvider dp = new XmlDataProvider();
            dp.Source = new Uri(@"C:\资料\f盘\代码\c#\WPF\TreeView\TestSource\Students.xml");
            dp.XPath = @"StudentList/Student";
            this.listView1.SetBinding(ListView.ItemsSourceProperty, new Binding() { Source=dp});

4.使用LINQ做为数据源

从3.0版本,.NET Framework开始支持LINQ,使用LINQ,可以方便的操作集合对象,LINQ查询结果是一个IEnumerable<T>类型对象,而IEnumerable<T>又派生自IEnumerable,所以可以作为列表控件的Items Source使用。

现在还还用刚开始创建的那个Student模型类和XAML代码,

public class Student
    {
        public int ID { get; set; }
        public String Name { get; set; }
    }
<StackPanel Height="300" Width="300" HorizontalAlignment="Left">
        <ListView Name="listView1">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="编号" DisplayMemberBinding="{Binding ID}" Width="100"></GridViewColumn>
                    <GridViewColumn Header="姓名" DisplayMemberBinding="{Binding Name}" Width="100"></GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </StackPanel>

我们只需更改数据源即可

 List<Student> stus = new List<Student>()
            {
                new Student(){ID=1,Name="狗娃"},
                 new Student(){ID=2,Name="铁蛋"},
                 new Student(){ID=3,Name="狗剩"}
            };
            this.listView1.ItemsSource = from stu in stus where stu.Name.StartsWith("狗") select stu;

还可以将数据放在DataTable中

 DataTable dt = CreateDt();
            DataRow dr = dt.NewRow();
            dr[0] = 1;
            dr[1] = "狗娃";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 2;
            dr[1] = "狗剩";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 1;
            dr[1] = "铁蛋";
            dt.Rows.Add(dr);

            this.listView1.ItemsSource = from row in dt.Rows.Cast<DataRow>()
                                         where (row["Name"] as String).StartsWith("狗")
                                         select new Student
                                         {
                                             ID = Convert.ToInt32(row["ID"]),
                                             Name = row["Name"] as String
                                         };

又或者使用XML

 XDocument xd = XDocument.Load(@"C:\资料\f盘\代码\c#\WPF\TreeView\TestSource\Students.xml");
            this.listView1.ItemsSource = from ele in xd.Descendants("Student")
                                         where (ele.Elements().First()).Value.StartsWith("狗")
                                         select new Student
                                         {
                                             ID = Convert.ToInt32(ele.Attribute("id").Value),
                                             Name = ele.Elements().First().Value

5.ObjectDataProvider做为数据源

理想情况下,上游程序员将类设计好,使用属性把数据暴露出来,下游程序员将这些类作为Binding的Source,把属性做为Binding的Path来消费。但很难保证一个类的属性都暴露出来,例如需要的数据可能是方法的返回值。而重新设计底层类的风险会比较高,况且有可能引用的类库情况我们不可能更改已经便宜好的类,这时候就需要使用ObjectDataProvider来包装做为Binding源的数据对象。

ObjectDataProvider顾名思义就是把对对象做为数据源提供给Binding。上面使用的XmlDataProvider,这两个类的父类都是DataSourceProvider抽象类。

现在做一个这样例子。

有一个Calculator类,它具有一个加法方法

class Caculate
    {
        public string Add(string arg1, string arg2)
        {
            double x = 0;
            double y = 0;
            double z = 0;
            if (double.TryParse(arg1, out x) && double.TryParse(arg2, out y))
            {
                z = x + y;
                return z.ToString();
            }
            return "Iput Error";
        }

    }

然后在XAML中创建三个TextBox框

<StackPanel Height="300" Width="300" HorizontalAlignment="Left">
        <TextBox Name="txtBox1" Width="120" HorizontalAlignment="Left"></TextBox>
        <TextBox Name="txtBox2" Width="120" Margin="0 10" HorizontalAlignment="Left"></TextBox>
        <TextBox Name="txtBox3" Width="120" Margin="0 10"  HorizontalAlignment="Left"></TextBox>
    </StackPanel>

要实现的需求就是通过Caculate方法实现第三个文本框是前两个之和,也就是我们需要将前两个文本框绑定到Add方法的两个参数,第三个绑定到返回值上。

然后我们在构造函数中编写后台代码

  ObjectDataProvider odp = new ObjectDataProvider();
            //设置用于绑定源的对象
            odp.ObjectInstance = new Caculate();
            //设置调用方法的名称
            odp.MethodName = "Add";
            //添加方法参数
            odp.MethodParameters.Add("0");
            odp.MethodParameters.Add("0");
            //绑定参数到txtBox1和txtBox2
            this.txtBox1.SetBinding(TextBox.TextProperty, new Binding("MethodParameters[0]") { Source = odp, BindsDirectlyToSource = true, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            this.txtBox2.SetBinding(TextBox.TextProperty, new Binding("MethodParameters[1]") { Source = odp, BindsDirectlyToSource = true, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            //绑定结果
            this.txtBox3.SetBinding(TextBox.TextProperty, new Binding(".") { Source = odp});

先来分析一下上面代码。ObjectDataProvider类的作用是包装一个以方法暴露数据的对象,这里就先创建一个ObjectDataProvider的对象.然后用一个Caculate对象做为ObjectInstance对象复制。这就是把Caculate对象包装在了ObjectDataProvider里面。接着使用MethodName属性指定调用的Caculate对象中Add的方法。问题来了,如果Caculator有多个构造器参数的方法Add应该如何区分?我们知道,重载方法的区别在于参数列表,紧接着两句就是向MethodParameter属性里面加入两个string类型的参数,这就相当于告诉ObjectDataProvider对象去调用Caculator对象中具有两个string类型参数的Add方法,换句话说,MethodParameter对于参数的感应是非常敏感的。

准备好数据源之后,我们准备创建Binding。前面我们已经讲过使用索引器作为Binding的Path,第一个Binding它的Source是一个ObjectDataProvider对象,Path是ObjectDataProvider中MethodParameters所引用的第一个元素。BindsDirectlyToSource这句话是告诉Binding只是将UI上的值传递给源而不是被ObjectDataProvider包装的Caculator,同时UpdateSourceTrigger设置为UI只要一有变化就更新Source。第二个Binding只是对第一个的翻版,只是把Path属性指向了第二个元素。第三个binding仍然使用ObjectDataProvider作为Source,但使用“.”作为Path----前面讲过,当数据源本身就是数据的时候就用“.”来做为Path,在XAML中"."可以不写。

注意:  在ObjectDataProvider对象作为Binding的Source的时候,这个对象本身就代表了数据,所以这里的Path使用的“.”,而不是Data属性。

原文地址:https://www.cnblogs.com/yan7/p/8322291.html

时间: 2024-10-30 05:14:15

WPF Binding学习(四) 绑定各种数据源的相关文章

WPF Binding学习(二)

Binding作为数据的桥梁,连通业务逻辑层的对象(源对象)和UI的控件对象(目标对象).在这座桥梁上,我们不仅可以控制在源对象与目标对象是双向通行还是单向通行.还可以控制数据的放行时机,甚至可以在这座桥上搭建一些关卡用来转换数据类型或者检验数据的正确性 我们先做一个最基本的例子, 创建一个"Student"类,这个类的实例将作为数据源来使用 public class Student { private int _id; public int ID { get { return _id

WPF Binding学习(三)

转自;http://blog.csdn.net/lisenyang/article/details/18312199 1.控件与控件间的双向绑定 WPF还支持控件作为数据源, <TextBox Name="txt_Source" Width="120" HorizontalAlignment="Left"></TextBox> <TextBox Text="{Binding ElementName=txt_

《深入浅出WPF》学习笔记之深入浅出话Binding

Binding作为数据的桥梁,它的两端分别是Binding的源(Source)和目标(Target),用来把Source中的数据送到Target中,并把在Target中的改变返回到Source.一般情况,Binding的源是逻辑层的对象,目标是UI层的控件对象. Binding的基本使用方法 如果想让作为数据源的对象在发生更改时自动显示到界面上,数据源的对象需要实现INotifyPropertyChanged接口.设置绑定时需要指定绑定到数据源的哪个属性,这个属性称为Binding的路径Path

WPF的Binding学习笔记(二)

原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的皮毛, 然后就做别的事去了, 等回头再来看WPF的时候, 哈忘记了~ 于是写个例子补一下, 在继续学习Binding. 1, 首先准备好一个类 public class Hero { public Hero(int id, string name, string skill, bool hasM)

WPF中使用ObjectDataProvider绑定方法

原文:WPF中使用ObjectDataProvider绑定方法 ObjectDataProvider提供了绑定任意.net类型的功能,具体功能如下: 1.ObjectDataProvider提供了绑定任意CLR类型的公嫩那个. 2.它可以再XAML中利用生命史的语言以及参数化的构造函数完成对数据的创建 3.增加对成员函数的绑定 4.提供了更多的异步绑定的功能 下面用一个加法计算器来进行实例说明: 请先看我们的加法类: C#代码 namespace BindingDemo {     public

Silverlight学习(四) domainservice动态多条件查询

上次讲了silverlight+MVVN+EF的简单框架,能够实现简单的数据CURD,但是多条件动态的查询一直没有实现.在网上查阅了很多资料,发现自己走了很多误区,代码很难调试正确. 这次的查询是基于上次的查询,只是增加了一个查询条件,动态多条件的查询的重点是获取查询的语言. 1 private string GetSql() 2 { 3 string query = "1=1"; 4 if (!string.IsNullOrEmpty(searchText.name)) 5 { 6

WPF入门教程系列(二) 深入剖析WPF Binding的使用方法

WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProperty)只能拥有一个binding. 这一点可以通过设置binding对象的方法名得知: public static BindingExpressionBase SetBinding( DependencyObject target, DependencyProperty dp, BindingB

WPF自定义控件(四)の自定义控件

在实际工作中,WPF提供的控件并不能完全满足不同的设计需求.这时,需要我们设计自定义控件. 这里LZ总结一些自己的思路,特性如下: Coupling UITemplate Behaviour Function Package 下面举例说说在项目中我们经常用到调音台音量条,写一个自定义控件模拟调音台音量条. 自定义控件SingnalLight,实现功能 接收来自外部的范围0~100的数值 实时显示接收数值 数值范围0~50显示绿色,50~85显示黄色,85~100显示红色,没有数值显示褐色 可在父

WPF BINDING

WPF里分三种Binding:Binding, PriorityBinding, MultiBinding,这三种Binding的基类都是BindingBase,而BindingBase又继承于MarkupExtension Binding 提供对绑定定义的高级别访问,绑定将绑定目标对象(通常为 WPF 元素)的属性与任何数据源(例如数据库.XML 文件或包含数据的任何对象)连接起来. 常见的使用Binding的代码:C# Binding binding = new Binding(); //