数据绑定

来源:互联网 发布:windows打印原理 编辑:程序博客网 时间:2024/05/29 04:04

 XAML绑定语法:

上边的代码我们将名为txtName的对象的Text属性作为源对象分别绑定给了两个TextBlockText属性。这里我们用了Binding关键字并指定了ElementNamePath,这两个就是指定源对象(Source)和源属性(Source Property). 通常我们在设定绑定时都用与StaticResource标记类似的语法{Binding… }并设置ElementNamePath属性:

Text=”{Binding ElementName=SourceObjectName, Path=SourceProperty}”

 

·         Coding(C#)添加Binding

而对于C#里和绑定相关的代码,则看起来会罗嗦很多。但它们都同样的使用了Binding对象,然后指定PropertyPath的一个实例为源属性,然后可以有两个方法来加载绑定规则:

1.       调用FrameworkElement FrameworkContentElement对象的SetBinding方法

2.       调用BindingOperations.SetBinding静态方法

以下代码实现了和上边XAML文件类似的功能:

Binding binding = new Binding();

//设置源对象

binding.Source = txtName;

//设置源属性

binding.Path = new PropertyPath("Text");

//添加到目标属性

this.tbShowMessage.SetBinding(TextBlock.TextProperty, binding);

//or

//BindingOperations.SetBinding(tbShowMessage, TextBlock.TextProperty, binding);

 

·         Coding(C#)移除Binding

当你在应用程序中某个地方添加了绑定,而在某个时候又不想这个绑定在接下来继续有效时,你可以有两种方式来断开这个绑定:

1.       用BindingOperations.ClearBinding静态方法。

例如BindingOperations.ClearBinding(currentTextBlock, TextBlock.TextProperty); BindingOperations同时还提供了ClearAllBindings方法,只需要传入要清除绑定的目标对象的名称,它就会将所有这个对象的绑定移除。

2.       简单的将目标属性设置为一个新的值。

这个简单的方法同样有效,可以断开与前边设置的binding的连接。简单的设置为任何值即可:如:currentTextBlock.Text = “it’s a new value.”;

·         Binding对象的属性

Property

Description

Converter

转换器

ElementName

绑定的源对象

FallbackValue

绑定无法返回有效值时的默认显示。

Mode

绑定方式

Path

属性

RelativeSource

常用于自身绑定或者数据模板中来指定绑定的源对象。

Source

源对象

StringFormat

格式化表达式

UpdateSourceTrigger

Sets the events on which binding will occur.

ValidationRules

验证规则

 

总结:对于对象间的绑定,绑定源为ElementName,Path为绑定源属性。ElementName必须为以下可选项之一:

DataContext

DataContext是WPF最后才试图查找的源。一旦RelativeSource和Source对象都没有被设置,则会在逻辑树种向上搜寻。

RelativeSource

用来标识和当前控件关联的对象,通常用于自我引用或数据模板。

Source

数据提供者/对象

 

2.     绑定到集合

 

·         利用ItemsSource来绑定数据源

常用标记:{Binding Path =””}    ItemSource    DisplayMemberPath 

通常来说这是我们在做以数据驱动为主的应用时最经常用到的绑定方式。WPF支持任何类型的.NET对象作为数据源绑定到WPF对象。对于所有的ItemsControl对象都有一个ItemsSource依赖属性,这是专门为数据绑定而准备的。ItemsSource的类型是IEnumerable,所以对于我们几乎所有的集合类型我们都可以轻易的改变成ItemsSource的源对象。通过以下语句我们可以将一个名为photos的集合赋予ListBox对象,并以显示Name属性的值:

<ListBox x:Name=”pictureBox” DisplayMemberPath=”Name” 

ItemsSource=”(Binding {DynamicResource photos}”

我们知道,依赖属性内建的垂直通知功能让UI对象间的绑定可以自己负责同步处理,但是对于.NET集合/对象来讲,它不具备这样的能力。为了让目标属性与源集合的更改保持同步,源集合必须实现一个叫INotifyCollectionChanged的接口,但通常我们只需要将集合类继承于ObservableCollection类即可。因为ObservableCollection实现了INotifyPropertyChangedINotifyCollectionChanged接口。示例代码中我们这么去定义Photos集合类:

public class Photos : ObservableCollection<Photo>

·         利用DataContext来作为共享数据源

常用标记:{Binding Path=””}   DataContext

顾名思义,DataContext就是数据上下文对象,它是为了避免多个对象共享一个数据源时重复的对所有对象显式地用binding标记每个Source/RelativeSource/ElementName,而把同一个数据源在上下文对象的某个范围内共享,这样当一个绑定没有显式的源对象时,WPF会便利逻辑数找到一个非空的DataContext为止。

例如我们可以通过以下代码给ListBoxTitle设置绑定:

<StackPanel Orentation=”Vertical” Margin=”5” DataContext=”{DynamicResource photos}”>

<Label x:Name=”TitleLabel” Content=”{Binding Path=Count}” DockPanel.Dock=”Bottom” />

<ListBox x:Name=”pictureBox” DisplayMemeberPath=”Name” ItemSource=”{Binding}” />

</StackPanel>

 

对于这些简单的绑定我们可以很灵活的组合他们的应用来达到我们的要求,这也是我们通常使用的方法。例如:

<Window.Resources>

     <local:Employee

        x:Key="MyEmployee" EmployeeNumber="123" FirstName="John"

       LastName="Doe" Department="Product Development" Title="QA Manager" />

</Window.Resources>

<Grid DataContext="{StaticResource MyEmployee}">

    <TextBox Text="{Binding Path=EmployeeNumber}"></TextBox>

    <TextBox Text="{Binding Path=FirstName}"></TextBox>

    <TextBox Text="{Binding Path=LastName}" />

    <TextBox Text="{Binding Path=Title}"></TextBox>

    <TextBox Text="{Binding Path=Department}" />

</Grid>

 

总结:对于集合的绑定,通常会需要用到以下几个标记:

DisplayMemberPath

指定源对象中被显示的属性。ToString()方法会被默认调用。

ItemsSource

指定要显示的数据源

ItemsTemplate

指定以什么样的格式来显示数据(类似于符合控件,可以在数据模板中利用多种控件来控制展现方式)

Path

数据源对象中的属性—控制显示

DataContext

共享数据源

 

 

3.     数据模板 – Data Template

当源属性和目标属性为兼容的数据类型,且源所显示的东西正是你需要显示的东西时,数据绑定确实很简单,你只需要向Section 1中讲的来匹配对象关系即可。而通常情况下我们对数据绑定都要做一些定制,特别对于.NET对象的绑定,你需要将数据源按照不同的方式分割显示。Data Template就负责来完成这样的功能:按照预想的数据展现模式将数据源的不同部分显示,而其作为可以被复用的独立结构,一旦定义可以被添加到一个对象内部,将会创建一个全新的可视树。

数据模板通常会被应用到以下几类控件来填充其类型为DataTemplate的属性:

·         内容控件(Content Control)ContentTemplate属性,控制Content的显示

·         项控件(Items Control)  ItemTemplate属性,应用于每个显示的项

·         头控件(Header Content Control)  HeaderTemplate属性,控制Header的展现。

每个数据模板的定义都是类似的方式,你可以像设计普通的窗体一样来设计其展现的方式,而且他们共享数据模板父空间所赋予的绑定源。例如下边的代码我们用一个图片来替代ListBox中的每一项:

    <ListBox x:Name="pictureBox" ItemsSource="{Binding}"ScrollViewer.HorizontalScrollBarVisibility="Disabled">

        <ListBox.ItemTemplate>

                    <DataTemplate>

                        <Image Source="{Binding Path=FullPath}" Margin="3,8" Height="35">

                            <Image.LayoutTransform>

                                <StaticResource ResourceKey="st"/>

                            </Image.LayoutTransform>

                            <Image.ToolTip>

                                <StackPanel>

                                    <TextBlock Text="{Binding Path=Name}"/>

                                    <TextBlock Text="{Binding Path=DateTime}"/>

                                </StackPanel>

                            </Image.ToolTip>

                        </Image>

                    </DataTemplate>

                </ListBox.ItemTemplate>

        </ListBox>

最终的ListBox中每一项的展现将按照我们在数据模板中设定的样式以图片来显示:

通常数据模板是不需要被内联声明的,它可以被定义成一个资源存放在Application.Resources这样的全局资源辞典中,或者单独的Resource Dictionary中在多个元素间共享。




绑定,就是把一个对象属性的值绑定在别的对象的属性上

1. 默认绑定

public class Company 

    public string Name { get; set; } 

 

XAML代码

1<StackPanel x:Name="stackPanel">
2    <TextBox x:Name="txtName" Text="{Binding Path=Name}"></TextBox>
3    <TextBox x:Name="txtName2" Text="{Binding  Path=Name}"></TextBox>
4    <Button Click="Button_Click">Ok</Button>
5</StackPanel>
后端代码:
01namespace DeepXAML
02{
03    public partial class MainWindow : Window
04    {
05        Company mCompany;
06        public MainWindow()
07        {
08            InitializeComponent();
09            mCompany = new Company { Name = "Microsoft" };
10            this.stackPanel.DataContext = mCompany;
11        }
12        private void Button_Click(object sender, RoutedEventArgs e)
13        {            
14            MessageBox.Show(this.mCompany.Name);
15            mCompany.Name = "Sun";
16        }        
17    }
18}

image 
我们把第一个文本框的值改为IBM,并点击按钮

 image

这个结果说明,我们绑定到一个普通的UI上时,前端的(绑定的目标)改变会时绑定的源改变。但我们第二次点击按钮时,出现如下的图

image

2. 双向绑定

上图后台使用代码改变对象的属性值,但前端绑定的值并未改变。那么如何让后台属性的变化通知到绑定的UI控件,让UI控件更新值呢?我们需要实现一个接口,现在我们对Company做如下改造

01namespace DeepXAML
02{
03   public  class Company:INotifyPropertyChanged
04    {
05        private string name;
06        public event PropertyChangedEventHandler PropertyChanged;
07        public string Name
08        {
09            get {return name; }
10            set {
11                name = value;
12                if (this.PropertyChanged != null)
13                
14                    this.PropertyChanged.Invoke(this,new PropertyChangedEventArgs("Name"));
15                }
16            }
17        }
18   }
19}

 

现在我们看一下我们点击按钮的结果,此时UI的值已经自动更新为后台更改的对象的值Sun了。

image

 

3.Binding的方向

<TextBox x:Name="txtName" Text="{Binding Path=Name, Mode=TwoWay}"></TextBox> 
<TextBox x:Name="txtName2" Text="{Binding  Path=Name, Mode=OneWay}"></TextBox>

这个在Binding时可以设置Mode.

image

oneWay:使用 OneWay 绑定时,每当源发生变化,数据就会从源流向目标。

OneTime: 绑定也会将数据从源发送到目标;但是,仅当启动了应用程序或 DataContext 发生更改时才会如此操作,因此,它不会侦听源中的更改通知。

OneWayToSource: 绑定会将数据从目标发送到源。

TwoWay: 绑定会将源数据发送到目标,但如果目标属性的值发生变化,则会将它们发回给源。

Default: binding的模式根据实际情况来定,如果是可编辑的就是TwoWay,只读的就是OneWay.

上面的例子不设Mode时,默认的就是Default.

 

4.如何用代码设定Binding

<StackPanel x:Name="stackPanel"> 
       <TextBox x:Name="txtName"></TextBox> 

</StackPanel>

image


http://www.cnblogs.com/zlgcool/archive/2008/10/22/1316605.html

http://www.cnblogs.com/luluping/archive/2011/05/06/2039475.html
0 0
原创粉丝点击