代码改变世界

Silverlight 4之旅(二)数据绑定(上)

2011-07-20 20:39  Henry Cui  阅读(4048)  评论(2编辑  收藏  举报

在上篇Post中通过一个简单的Demo,跟Silverlight有了一次接触,本篇文章中会就Silverlight 4中的绑定进行些说明。绑定可以说是Silverlight跟WPF中最为重要的技术,绑定的作用就是让我们的数据源跟SilverlightUI现实进行动态绑定。

绑定的基础概念

绑定是一种比较有效的建立UI跟Data之间的链接,在Silverlight中我们可以将UI的控件中的某个属性进行绑定,也可以将UI的几个属性之间进行相互绑定。绑定中有三个核心的概念:Source(数据源)、Binding Model(绑定模式)、Traget(目标UI)。这张图可以很好说明这三者之间的关系:

image

绑定的数据源一般是我们的CLR Object;Binding Mode是指我们使用绑定是所选择绑定的模式,共三种类型;目标我们的UI。我们先说说绑定的基本的语法。

语法基础

其实绑定的核心是通过Binding类建立Source跟Target之间的链接的,我们可以通过运行时指定,也可以通过在设计时进行指定。我们先看看运行时指定的语法:

首先我们在xaml中拥有如下控件:

<TextBox x:Name="dateTextBox" />

我们在后台代码中指定其绑定到当前时间:

var dateNow = DateTime.Now;
var binding = new Binding("dateNow");
binding.Source = dateNow;
binding.Mode = BindingMode.OneWay;
dateTextBox.SetBinding(TextBox.TextProperty, binding);

上面的代码的中,首先我们构建了Bingding对象,然后设置其Source以及BingdingMode,然后dateTextBox将其绑定设置到其TextProperty上面。这里面的Source即dateNow,BingMode选择的是OnWay的方式,Target即dateTextBox,正是上面说说的绑定的三个核心的概念。

下面我们看下如何在设计时指定:

<TextBox x:Name="dateTextBox" Text="{Binding TimeOfDay,Mode=OneWay}" />

在后台中我们指定了dateTextBox的DataContext属性:

var dateNow = DateTime.Now;
dateTextBox.DataContext = dateNow;

其实上面的{}方式只是一种简洁的方式,其实上面的绑定语法可以如此表达:

<TextBox x:Name="dateTextBox">
    <TextBox.Text>
        <Binding Path="TimeOfDay" Mode="OneWay"></Binding>
    </TextBox.Text>
</TextBox>

绑定Mode

绑定类型一共分为三种:1.OneTime;2.OneWay;TowWay.这三种模式在Source到Target绑定时,决定三种不同的绑定的类型。

1) OneTime

当我们使用OneTime绑定模式的时候,当Source发生改变的时候不会通知Target,只有在Source初始化时才会将其绑定到Target上面。

2) OneWay

OneWay是绑定Mode的默认值,在这种绑定的模式下,当Source发生改变的时候会通知并响应到Target上,如果Source的属性发生改变的时候,Target上面的属性就会自动改变。当时Target发生改变的时候,不会通知Source.

3) TwoWay

TowWay模式是指Target跟Source之间的改变会相互影响,我们在一些表单详细时会经常用到。

绑定Source

在绑定的源中,可以是一个CLR类型的Object,也可以是其他UI的某些属性上面,同事也可以绑定到自己本身的属性上面。下面我们来看下各种类型的绑定数据源的使用。

1)绑定到属性上面

在之前的例子里面我们看到了,将datetime的TimeOfDay绑定到了textblok上面,同时也是使用的OneWay的方式,即TimeOfDay发生改变,会更新到textblok上面,但是我们发现一个问题,就是现实的时候时间便没有自动更新。原因就是TimeOfDay属性没有做改变通知。我们回到第一篇文章中的Person类型,在这里面我们如何实现属性通知呢:

public class Person:INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _Name;
    public string Name
    {
        get { return _Name; }
        set {
            _Name = value;
            NotifyPropertyChanged("Name");
        }
    }

    private ImageSource _HeadImg;
    public ImageSource HeadImg
    {
        get { return _HeadImg; }
        set { 
            _HeadImg = value;
            NotifyPropertyChanged("HeadImg");
        }
    }

    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this,
            new PropertyChangedEventArgs(propertyName));
        }
    }
}

我们继承了INotifyPropertyChanged,INotifyPropertyChanged的作用就是做属性改变的广播通知,INotifyPropertyChanged可以保证我们在使用OneWay或则TowWay的模式的时候UI Target跟Source Property保证同步的。但是INotifyPropertyChanged的同步是通过 PropertyChangedEventHandler委托去告诉的,所以我们在属性改变时去触发事件PropertyChanged。

2)绑定到对象

在上面的例子里面我们主要都是看到了将一个数据源中的属性绑定上去的,其实更多的时候我们会将整个Object作为数据源来进行绑定。这个时候我们可以将Object指定到DataContext属性上面,DataContext是一个DepencyProperty允许我们共享数据,关键的是,我们在一个控件上指定了DataContext之后,其子element也可以使用到这个数据源。

我们在后台代码中:

var personList = GetPersons();
this.DataContext = personList[0];

前台Xaml中:

<Image Height="100" Width="100" Source="{Binding HeadImg}"></Image>
<TextBlock Text="{Binding Name}" FontSize="14" Margin="3"></TextBlock>

运行效果:

image

3)绑定到一个UIElement上面

SilverLight绑定源中也可以是UI控件的属性,我们来看下面的示例,一个新浪微博输入字符提示的示例,输入剩余字符个数的提醒:

<StackPanel Orientation="Vertical" Margin="50">
    <TextBox x:Name="weiboText"
    MaxLength="140"
    Text="Hi Henry" />
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Text.Length, ElementName=weiboText}" />
        <TextBlock Text="/" />
        <TextBlock Text="{Binding MaxLength, ElementName=weiboText}" />
    </StackPanel>
</StackPanel>

我们看到运行效果如下:

image

在上面的例子里面我们通过ElemetName属性去指定到某个控件上面。

4)绑定到集合类型上

其实在绑定到集合类型的数据源上面我们在上篇文章中见过了,主要需要指定其数据源到一个继承与ItemControl上的控件的ItemSource属性上。

总结

本篇文章中,主要介绍了绑定的基础知识、绑定的Mode的选择以及各种类型Source如何进行绑定。下篇文章中我们主要看下Target的显示问题。