Binding基础 文摘

简要

    • Binding基础
    • Binding源与路径
    • 列举Binding的源

Binding基础

从Coding中看Binding的基础。

先定义一个Student类:

public class Student : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
 
    private string name;
    public string Name
    {
        get
        {
            return this.name;
        }
        set
        {
            name = value;
            if (PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
            }
        }
    }
}XAML设计:
<StackPanel Height="70">
    <TextBox x:Name="textBoxName" BorderBrush="Black" Margin="5"></TextBox>
    <Button Content="Add Name" Margin="5" Click="Button_Click"></Button>
</StackPanel>后台部分:
public partial class MainWindow : Window
{
    Student stu;
 
    public MainWindow()
    {
        InitializeComponent();
        stu = new Student();
        Binding binding = new Binding();
        binding.Source = stu;
        binding.Path = new PropertyPath("Name");
 
        BindingOperations.SetBinding(this.textBoxName, TextBox.TextProperty, binding);
    }
 
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        stu.Name += "LiLin";
    }
}

在这个例子中,binding的源是stu,binding的路径是Name,既UI关心的那个属性。

首先,定义的Student实现了INotifyPropertyChanged接口,并在Name的set中激发PropertyChanged事件,这是为了是Binding机制能自动监听,并会通知Binding目标端的UI现实新的值。

在后台代码中,Binding部分是先声明Binding类型变量并创建实例,然后指定源与路径,最后使用BindingOperations.SetBinding(…)来实现数据源与目标的连接。

实际中,不需要这么麻烦地实现Binding,因为TextBox继承自FrameworkElement,对BindingOperations.SetBinding(…)进行了封装,提供SetBinding方法:

public BindingExpressionBase SetBinding(DependencyProperty dp, BindingBase binding)
{
    return BindingOperations.SetBinding(this, dp, binding);
}使用SetBinding可以简化为:
InitializeComponent();
stu = new Student();
this.textBoxName.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = stu });

Binding的源与路径

Binding的源只要是一个对象,且拥有公开的属性。可以是实现了INotifyPropertyChanged接口的自定义类、控件、集合、XML…

把控件作为Binding的源:

<StackPanel Height="70">
    <TextBox x:Name="textBoxValue" BorderBrush="Black" Margin="5" Text="{Binding Path=Value, ElementName=slider, UpdateSourceTrigger=PropertyChanged}"></TextBox>
    <Slider x:Name="slider" Maximum="100" Minimum="0" Margin="5"></Slider>
</StackPanel>

控制Binding的方向和数据更新触发方式:

控制Binding数据流向的属性是Mode,枚举。可以取值为:TwoWay、OneWay、OnTime、OneWayToSource、Default。

控制数据更新触发方式的属性是UpdateSourceTrigger,类型是UpdateSourceTrigger枚举,可以取值为:PropertyChanged、LostFocus、Explicit和Default。

Binding的路径:

Binding的路径是指示Binding关注的属性。

为Binding指定源的几种方法:

  1. 把普通的CLR类型单一对象指定为Source:该类型需实现INotifyPropertyChanged接口,并通过属性的Set语句里激发PropertyChanged事件;
  2. 把普通的CLR集合类型对象指定为源:包含数组、List<T>、ObservableCollection<T>等集合类型;
  3. 把ADO.NET数据对象指定为源:有DataTable和DataView等对象;
  4. 使用XmlDataProvider把XML数据指定为Source;
  5. 把以来对象指定为源;
  6. 把容器的DataContext指定为源;
  7. 通过ElementName指定源:用于XAML中;
  8. 通过Binding的RelativeSource属性相对指定Source:当控件需要关注自己的、自己容器的或者自己内部元素的某个值就需要使用到这个属性;
  9. 把ObjectDataProvider对象指定为源;
  10. 把使用LINQ检索得到的数据对象作为源。

    使用DataContext作为Binding的源:

    DataContext是定义在WPF控件基类FrameworkElement中,因此所有WPF控件都有这个属性。

    简单例子:

    <Window x:Class="BindBasicTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:BindBasicTest"
            Title="MainWindow" Height="150" Width="230">
        <StackPanel Height="100">
            <StackPanel.DataContext>
                <local:Student Id="100" Name="LiLin" Age="18"></local:Student>
            </StackPanel.DataContext>
            <TextBox Text="{Binding Path=Id}" Margin="5"></TextBox>
            <TextBox Text="{Binding Path=Name}" Margin="5"></TextBox>
            <TextBox Text="{Binding Path=Age}" Margin="5"></TextBox>
        </StackPanel>
    </Window>

    使用集合对象作为列表控件的ItemsSource:

    列表控件都是派生自ItemsControl类,则都继承了ItemsSource这个属性。ItemsSource属性可以接受一个IEnumerable接口的派生类。只要为ItemsControl对象设置ItemsSource属性值,ItemsSource就会自动迭代其中的数据。

    例子:

    XAML设计:

    StackPanel Background="LightBlue">
        <TextBlock Text="Student ID" FontWeight="Bold" Margin="5"></TextBlock>
        <TextBox x:Name="txtBoxId" Margin="5"></TextBox>
        <TextBlock Text="Student List" FontWeight="Bold" Margin="5"></TextBlock>
        <ListBox x:Name="listBoxStudent" Height="80"></ListBox>
    </StackPanel>后台代码:
    public MainWindow()
    {
        InitializeComponent();
     
        List<Student> stu_list = new List<Student>()
        {
            new Student(){Id=0,Name="LiLin",Age=18},
            new Student(){Id=1,Name="LinLi",Age=20},
            new Student(){Id=2,Name="LLiin",Age=24},
            new Student(){Id=3,Name="Tom",Age=27},
            new Student(){Id=4,Name="Tim",Age=19},
            new Student(){Id=5,Name="Luke",Age=23},
        };
     
        this.listBoxStudent.ItemsSource = stu_list;
        this.listBoxStudent.DisplayMemberPath = "Name";
     
        this.txtBoxId.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id") { Source = this.listBoxStudent });
     
    }this.listBoxStudent.DisplayMemberPath = "Name";这是设置listbox显示字段,如果要显示多个或者全部字段呢。这就要使用到类型为DataTemplate的ItemTemplate属性(继承自ItemsControl类),通俗的说是换衣服。在XAML中修改代码,并把this.listBoxStudent.DisplayMemberPath = "Name";删除:
    <ListBox x:Name="listBoxStudent" Height="80">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Id}" Width="30" Foreground="Red"></TextBlock>
                    <TextBlock Text="{Binding Path=Name}" Width="50"></TextBlock>
                    <TextBlock Text="{Binding Path=Age}" Width="30"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    注意事项:使用集合对象作为列表控件的ItemsSource时,一般会使用ObservableCollection<T>代替List<T>,理由是,ObservableCollection<T>实现了INotifyCollectionChanged和INotifyPropertyChanged接口。

    使用ADO.NET对象作为Binding对象:

    在WPF中支持列表控件与DataTable直接建立Binding。假设已经获得了一个DataTable的实例,数据跟以上的一样。现在Coding把它显示在ListBox中:

DataTable dt = Load();
 
this.listBoxStudent.ItemsSource = dt.DefaultView;

换件“衣服”:

<ListView x:Name="listViewStudent" Height="120" Margin="5">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Id" Width="60" DisplayMemberBinding="{Binding Id}"></GridViewColumn>
            <GridViewColumn Header="Name" Width="80" DisplayMemberBinding="{Binding Name}"></GridViewColumn>
            <GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}"></GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

有点注意的:ListView和GridView不是同一级别的控件。ListView是继承自ListBox,GridView是ViewBase的派生类,ListView的View属性是ViewBase的对象。因此,GridView可以作为ListView的View来使用。

如果想用更复杂的结构来表示标题或者数据,可以为GridViewColumn设置HeaderTemplate和CellTemplate属性,类型都是DataTemplate。

使用XML数据作为Binding的源: 
现在程序中涉及到数据传输都离不开XML。XML文本是树形结构,可以方便地用于表示线性集合。

先Coding一个:

有这么一个Student.xml,

<?xml version="1.0" encoding="utf-8" ?>
<StudentList>
  <Student Id="1">
    <Name>LiLin</Name>
  </Student>
  <Student Id="2">
    <Name>Tom</Name>
  </Student>
  <Student Id="3">
    <Name>Tim</Name>
  </Student>
  <Student Id="4">
    <Name>Luke</Name>
  </Student>
  <Student Id="5">
    <Name>Jake</Name>
  </Student>
  <Student Id="6">
    <Name>LiLi</Name>
  </Student>
</StudentList>XAML:
<ListView x:Name="listViewStudent" Height="120" Margin="5">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Id" Width="60" DisplayMemberBinding="{Binding [email protected]}"></GridViewColumn>
            <GridViewColumn Header="Name" Width="80" DisplayMemberBinding="{Binding XPath=Name}"></GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>后台:
mlDocument xdoc = new XmlDocument();
xdoc.Load(@"C:\Student.xml");
XmlDataProvider xdp = new XmlDataProvider();
xdp.Document = xdoc;
xdp.XPath = @"/StudentList/Student";
 
this.listViewStudent.DataContext = xdp;
this.listViewStudent.SetBinding(ListView.ItemsSourceProperty, new Binding());

注意:XAML中DisplayMemberBinding="{Binding [email protected]}"和DisplayMemberBinding="{Binding XPath=Name}"之间的@差异,指明了关注的xml路径不同,使用@表示是XML元素的Attribute,不加的是指子集元素。

使用LINQ检索结果作为Binding的源:

因为LINQ查询结果是一个IEnumerable<T>类型的对象,而IEnumerable<T>继承了IEnumerable,所以它可以作为列表控件的ItemsSource来使用。

Coding:

List<Student> stu_list = new List<Student>()
{
    new Student(){Id=0,Name="LiLin",Age=18},
    new Student(){Id=1,Name="LinLi",Age=20},
    new Student(){Id=2,Name="LLiin",Age=24},
    new Student(){Id=3,Name="Tom",Age=27},
    new Student(){Id=4,Name="Tim",Age=19},
    new Student(){Id=5,Name="Luke",Age=23},
};
 
this.listViewStudent.ItemsSource = from stu in stu_list where stu.Age <= 20 select stu;
时间: 2024-08-13 15:59:35

Binding基础 文摘的相关文章

WPF Data Binding之地位与基础【一】

[1]Data Binding在WPF中的地位 从传统的Winform转移到WPF上,对于一个三层程序而言,数据存储层由数据库和文件系统组成,数据传输和处理仍然使用.NetFramework的ADO.NET等基本类(与Winform开发一样).展示层则使用WPF类库来实现,而展示层和逻辑层的沟通就使用Data Binding来实现.可见,Data Binding在WPF中所起的作用就是高速公路的作用.有了这条高速公路,加工好的数据自动送达用户界面并加以显示,被用户修改过的数据也会自动传回业务逻辑

【转载一篇WPF之Binding】WPF之Binding深入探讨

1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的程序来说,算法一般分布在这几处: A.数据库内部. B.读取和写回数据. C.业务逻辑. D.数据展示. E.界面与逻辑的交互. A,B两部分的算法一般都非常稳定,不会轻易去改动,复用性也很高:C处与客户需求最紧密,最复杂,变化最大,大多少算法都集中在这里.D,E负责UI和逻辑的交互,也占有一定量的

WPF学习之Binding的学习(一)

程序的本质是数据加算法.通俗一点来说呢,其实就是用户给一个输入,经过算法的处理之后,计算机反馈一个输出给用户.可以很清楚的看出,在这个过程中,处于主导地位的是数据.但是,当我们在进行图形用户界面(Graphic User Interface,GUI)编程的时,数据总是处于被动地位.也就是说,程序总是在等待接收来自UI的消息/事件,在这些事件被处理之后,才会反馈给用户一个输出.我们用Data Binding可以在GUI编程时让数据回到程序的核心. **1.Data Binding在WPF中的地位*

Binding笔记

Binding基础  绑定某个对象的属性值到控制上,写法如下: public class Order : INotifyPropertyChanged//只要实现此接口 { public event PropertyChangedEventHandler PropertyChanged; private string orderNo; public string OrderNo { get { return orderNo; } set { orderNo = value; if (Proper

Binding

Binding基础  绑定某个对象的属性值到控制上,写法如下: public class Order : INotifyPropertyChanged//只要实现此接口 { public event PropertyChangedEventHandler PropertyChanged; private string orderNo; public string OrderNo { get { return orderNo; } set { orderNo = value; if (Proper

WPF之Binding深入探讨

1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都非常重要.但算法在3层中的分布是不均匀的,对于一个3层结构的程序来说,算法一般分布在这几处: A.数据库内部. B.读取和写回数据. C.业务逻辑. D.数据展示. E.界面与逻辑的交互. A,B两部分的算法一般都非常稳定,不会轻易去修改,复用性也非常高:C处与客户需求最紧密,最复杂,变化最大,大多少算法都集中在这里.D,E负责UI和逻辑的交互,也占有一定

WPF之Binding【转】

WPF之Binding[转] 看到WPF如此之炫,也想用用,可是一点也不会呀. 从需求谈起吧: 首先可能要做一个很炫的界面.见MaterialDesignInXAMLToolKit. 那,最主要的呢,还是想显示数据. 就先来数据,数据可以从数据库里得到,可是如何显示出来呢? 本文的主角出来了:(以下内容全转载他人,具体 原文见上面的链接) ==================================== 1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.

WPF学习之Binding(一)

Binding WPF的核心理念是传统的变UI驱动程序为数据驱动UI,支撑这个理念的基础就是Data Binding和与之相关的数据校验和转换. 使用Binding时,最重要的是准确设置它的源和路径. Binding基础 Binding是数据的桥梁,两端分别是Source(源)和Target(目标) 例子:创建一个简单的数据源binding在UI元素上 创建数据源(student类) class Student : INotifyPropertyChanged { public event Pr

《深入浅出WPF》学习总结之Binding

一.前言 友好的图形用户界面(Graphics User Interface ,GUI)的流行也就是近十来年的事情,之前应用程序与用户的交互是通过控制台界面(Console User Interface ,CUI)完成的.图形用户界面的操作系统开始在中国流行应该是从Windows 95正式发布开始的,旋即冠以Visual的开发工具(以及Borland公司的一些同类产品)也跟着崭露头角.记得那时候硬件能跑起来Windows 95的就已经相当不错了——图形化的界面还是很消耗硬件资源的. GUI作为新