Silverlight中的数据绑定2

Silverlight中数据绑定,须由自己决定要使用的绑定模式,在前面一篇文章中都是使用了默认模式OneTime

银光中支持3种模式

   OneTime  :仅在数据进行绑定时发生一次,以后更改绑定源对输出不产生任何影响
   OneWay  :数据绑定只在从绑定源到绑定目标这一个方向起作用,即更改绑定源会更改绑定目标,且不需要在代码中进行额外的处理
   TwoWay  :更改绑定源会更改绑定目标,反之亦然。

其中OneWay和TwoWay类似ASP.NET中的Eval与Bind绑定,需要注意的是,若使用这两者绑定模式,需要实现INotifyPropertyChanged接口

单向数据绑定

Xaml代码只是在之前的基础上添加了一个充当文本的按钮

 <Grid x:Name="PersonalPanel" Background="White">

        <TextBlock Height="23" HorizontalAlignment="Left" Margin="88,53,0,0" Name="textBlock3" Text="{Binding FirstName}" VerticalAlignment="Top" />
        <TextBlock Height="23" HorizontalAlignment="Left" Margin="89,116,0,0" Name="textBlock4" Text="{Binding LastName}" VerticalAlignment="Top" />
        <Canvas Canvas.Left="120">   
        <Polygon Fill="Black" Points="0,5,10,0,10,10" MouseLeftButtonDown="prev"></Polygon>    
       <Polygon Fill="Black" Points="15,0,15,10,25,5" MouseLeftButtonDown="next"></Polygon> 
          <TextBlock Text="Reverse" Canvas.Left="40" Canvas.Top="20" FontSize="13" MouseLeftButtonDown="reverse"></TextBlock>
        </Canvas>   
</Grid>

在此基础上完成单击时,使用reverse方法实现FirstName与LastName中的文本顺序颠倒

 public void reverse()
        {
            char [] c=new char[this.FirstName.Length];
            for (int i = 0; i < this.FirstName.Length; i++)
            {
                c[i] = this.FirstName[this.FirstName.Length - 1 - i];
            }
            this.FirstName = new String(c);
            c = new char[this.LastName.Length];
            for (int i = 0; i < this.LastName.Length; i++)
            {
                c[i] = this.LastName[this.LastName.Length - 1 - i];
            }
            this.LastName = new string(c);
        }

接下来需要一个在更改属性时实现的公共事件:

public event PropertyChangedEventHandler PropertyChanged;

但是此事件无法自动使用,我们改写代码触发此事件,

 
        private string firstName;
        public string FirstName
        {
            get { return firstName; }
            set { firstName = value;
            if (PropertyChanged != null)
            {
           PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
            }
            }
        } 

最后实现鼠标单击的事件处理程序 Person类文件的完整代码:

 private string firstName;

        public string FirstName
        {
            get { return firstName; }
            set { firstName = value;
            if (PropertyChanged != null)
            {
            PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
            }
            }
        }  
        //为进行演示,只对FirstName进行额外处理
        public string LastName { get; set; }
        public void reverse()
        {
            char [] c=new char[this.FirstName.Length];
            for (int i = 0; i < this.FirstName.Length; i++)
            {
                c[i] = this.FirstName[this.FirstName.Length - 1 - i];
            }
            this.FirstName = new String(c);
            c = new char[this.LastName.Length];
            for (int i = 0; i < this.LastName.Length; i++)
            {
                c[i] = this.LastName[this.LastName.Length - 1 - i];
            }
            this.LastName = new string(c);
        }

        public event PropertyChangedEventHandler PropertyChanged;

不要忘记添加System.ComponentModel命名空间

后台代码:

 public partial class MainPage : UserControl
    {
        private int pos = -1;
        private Person[] persons;
        public MainPage()
        {
            InitializeComponent();
          
            persons = new Person[] 
            {
             new Person{FirstName="David",LastName="Grenn"},
             new Person{FirstName="Dam",LastName="White"},
             new Person{FirstName="Tom",LastName="Smith"},
            };
        }
        public void prev(object sender, MouseButtonEventArgs e)
        {
            if (pos > 0)
                pos--;
            bind();
        }
        public void next(object sender, MouseButtonEventArgs e)
        {
            if (pos < persons.Length - 1)
                pos++;
            bind();
        }
        private void bind()
        {
            PersonalPanel.DataContext = persons[pos];
        }
        private void reverse(object sender, MouseButtonEventArgs e)
        {
            persons[pos].reverse();
        }

运行时,会发现当单击Reverse时,只有名字颠倒了顺序,但是如果移动到下一个(或上一个),然后返回到之前的记录,会发现两者都颠倒了,原因在于只有FirstName属性触发了PropertyChanged事件,因此只更新名字的显示,但是当前进或者后退时,数据总是会再次绑定到元素上,因此会出现两者全部颠倒的情况。

双向数据绑定

双向数据绑定可以使得显示数据的变化可以在原始数据中得到反映

为简化起见,在前面的示例中进行改写,只保留了其中关键的代码,主要是在绑定中添加了Mode枚举,我们把XAML代码修改为:

<Grid x:Name="PersonalPanel" Background="White">
<TextBox Name="textBlock3" Text="{Binding FirstName, Mode=TwoWay}" />
<TextBox Name="textBlock4" Text="{Binding LastName, Mode=TwoWay}" />
<Canvas Canvas.Left="120">
<Polygon Fill="Black" Points="0,5,10,0,10,10" MouseLeftButtonDown="prev"></Polygon>
<Polygon Fill="Black" Points="15,0,15,10,25,5" MouseLeftButtonDown="next"></Polygon>
</Canvas>
</Grid>

C#代码也进行了一点改变,lastname也实现了触发PropertyChanged事件

 private string lastName;
        public string LastName
        {
            get { return lastName; }
            set { 
                lastName = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("LastName"));
                }
            }
        }

其他代码部分则没有改变,运行时,当切换到某个字段时,(改变文本框内容后,需要使得文本框失去焦点),这时PropertyChanged事件会自动触发,

但是该事件不会在键入内容时立即触发,当单击下一条记录再返回时,因为使用了双向绑定,所以会自动传送给数据源。

posted @ 2010-05-16 18:00  ringgo  阅读(754)  评论(0编辑  收藏  举报