silverlight数据绑定模式TwoWay,OneWay,OneTime的研究

简介: asp.net开发中,数据绑定是一个很简单的概念,控件与数据绑定后,控件可以自动把数据按一定的形式显示出来。(当然控件上的值改变后,可以通过提交页面表单,同时后台服务端代码接收新值更新数据) silverlight中利用控件显示数据这一基本功能当然还保留,只不过因为silverlight应用不需要刷新(也不存在提交表单),所以当控件属性或数据源变化后,在如何相互影响这一块的处理上有所不同。

asp.net开发中,数据绑定是一个很简单的概念,控件与数据绑定后,控件可以自动把数据按一定的形式显示出来。(当然控件上的值改变后,可以通过提交页面表单,同时后台服务端代码接收新值更新数据)

silverlight中利用控件显示数据这一基本功能当然还保留,只不过因为silverlight应用不需要刷新(也不存在提交表单),所以当控件属性或数据源变化后,在如何相互影响这一块的处理上有所不同。

引用一段silverlight 3 sdk官方的解释:

...

Silverlight 支持以下三种类型的绑定:

创建 OneTime 绑定时,该绑定使用源数据更新目标。

创建 OneWay 绑定时以及每当源数据发生变化时,该绑定使用源数据更新目标。这是默认模式。

当目标和源有一个发生变化时,TwoWay 绑定既更新目标也更新源。或者,您可以禁用自动源更新,只在您选择的时间对源进行更新。

为了能够发生自动目标更新,源对象必须实现 INotifyPropertyChanged 接口,如下一部分所述。

...


简单的说:

OneTime模式下:控件与数据绑定后,能自动显示数据,一旦显示完成后,这二者就没有任何关联了。(即自动解除绑定)
OneWay模式下:控件与数据绑定后,除自动显示数据外,显示完成后,控件与数据源仍有单向关联,即如果数据源以后发生了变化,控件上的值也会自动变化.
TwoWay模式下:基本与OneWay相同,但是显示完成后,控件与数据源的关联是双向的,即数据源的变化会影响控件上的值,反过来控件上的任何值变化也会影响数据源本身发生变化。


来看一个简单的例子: 

< UserControl  x:Class ="BindingStudy.MainPage"
    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d
="http://schemas.microsoft.com/expression/blend/2008"  xmlns:mc ="http://schemas.openxmlformats.org/markup-compatibility/2006"  
    mc:Ignorable
="d" >
    
< StackPanel  x:Name ="LayoutRoot" >

        
< Rectangle  x:Name ="rect"  Stroke ="Black"  HorizontalAlignment ="Center"  VerticalAlignment ="Center"  Width =" {Binding Value, ElementName=silderSelf, Mode=OneTime} "   

Height
="80"   ></ Rectangle >

        
< Slider  Width ="200"  Minimum ="1"  Maximum ="200"  Value ="20"  x:Name ="silderSelf"  Margin ="0,10,0,0" ></ Slider >

        
< StackPanel  x:Name ="sp_Mode"  Orientation ="Horizontal"  HorizontalAlignment ="Center"  VerticalAlignment ="Center"  Margin ="0,10,0,0" >
            
< RadioButton  Content ="OneTime"  x:Name ="rboMode_OneTime"  GroupName ="bindMode"  IsChecked ="True"  Checked ="rboMode_OneTime_Checked" ></ RadioButton >
            
< RadioButton  Content ="OneWay"  x:Name ="rboMode_OneWay"  GroupName ="bindMode"  Margin ="10,0,0,0"  Checked ="rboMode_OneWay_Checked"   ></ RadioButton >
            
< RadioButton  Content ="TwoWay"  x:Name ="rboMode_TwoWay"  GroupName ="bindMode"  Margin ="10,0,0,0"  Checked ="rboMode_TwoWay_Checked"   ></ RadioButton >
        
</ StackPanel >
        
        
< StackPanel  x:Name ="sp_Button"  Orientation ="Horizontal"  HorizontalAlignment ="Center"  VerticalAlignment ="Center"  Margin ="0,10,0,0" >
            
< Button  x:Name ="btnWidthAdd"  Content ="矩形宽度+5px"  Click ="btnWidthAdd_Click" ></ Button >
            
< Button  x:Name ="btnWidthSub"  Content ="矩形宽度-5px"  Margin ="10,0,0,0"  Click ="btnWidthSub_Click" ></ Button >
        
</ StackPanel >
    
</ StackPanel >
</ UserControl >


解释一下:

最上面是一个矩形rect,下面是一个滑块拖动条silderSelf,其它的先不管,矩形的Width属性注意一下:

Width="{Binding Value, ElementName=silderSelf, Mode=OneTime}"

这里将矩形的宽度与滑块的Value值做了绑定(即矩形的宽度即为滑动条的值),模式为OneTime(即绑定完成后,二者再无任何关联)

tips:上面提到的绑定语法不用死记硬背,在Blend里用图形界面即可设置

选中矩形对象,点击属性面板Width右边的小黄点,弹出菜单中选择"Data Binding..."

设置绑定

运行效果: 

 

先不用急着关注其它东西,我们注意到矩形的宽度自动变成20了,即silder的value初始值,然后我们拖动滑块试下,矩形的宽度没有变化!也就映证了OneTime模式下,一旦绑定完成(数据显示结束),控件与数据源就再无任何瓜葛,大家各走各的路,各过各的桥。

为了测试另外二种模式,我在后台加了一些代码 :

using  System.Windows;
using  System.Windows.Controls;
using  System.Windows.Data;

namespace  BindingStudy
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif
{
    
public partial class MainPage : UserControl
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    
{
        
public MainPage()
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            InitializeComponent();
        }


        
private void rboMode_OneTime_Checked(object sender, RoutedEventArgs e)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
if (rect != null)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                Binding bindwidth 
= new Binding("Value");
                bindwidth.Mode 
= BindingMode.OneTime;
                
this.rect.SetBinding(UserControl.WidthProperty, bindwidth);
                
this.rect.DataContext = silderSelf;
            }

        }


        
private void rboMode_OneWay_Checked(object sender, RoutedEventArgs e)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
if (rect != null)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                Binding bindwidth 
= new Binding("Value");
                bindwidth.Mode 
= BindingMode.OneWay;
                
this.rect.SetBinding(UserControl.WidthProperty, bindwidth);
                
this.rect.DataContext = silderSelf;
            }

        }


        
private void rboMode_TwoWay_Checked(object sender, RoutedEventArgs e)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
if (rect != null)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                Binding bindwidth 
= new Binding("Value");
                bindwidth.Mode 
= BindingMode.TwoWay;
                
this.rect.SetBinding(UserControl.WidthProperty, bindwidth);
                
this.rect.DataContext = silderSelf;
            }

        }


       
        
private void btnWidthAdd_Click(object sender, System.Windows.RoutedEventArgs e)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
if (rect != null
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                rect.Width 
+= 5;
            }

        }


        
private void btnWidthSub_Click(object sender, System.Windows.RoutedEventArgs e)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
if (rect != null)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                rect.Width 
-= 5;
            }

        }

    }

}


代码不复杂,基本功能就是让绑定模式可以自由切换,相信大家一看就明白

这回我们来测试一下OneWay模式,运行后选择OneWay模式,然后再手动拖动滑块,会发现矩形的宽度随着滑块的值不断变化,即OneWay模式下,数据源的变化会自动反应在绑定的目标控件上,继续,我们点击最下面的二个按钮,改变矩形的宽度,发现滑块不会自己移动,这说明了OneWay模式下控件的属性变化,不会反过来影响数据源本身。


最后切换到TwoWay模式,与OneWay模式的不同之外在于,如果我们点击最下面的按钮,改变矩形的宽度,会发现滑块自己移动了,移动后的值即为矩形的宽度,结论:TwoWay模式下,控件与数据源任何一方的变化都会影响对另一方。(个人感觉这个功能很NB,如果我们自己实现的话,不知道要写多少行代码!)


当然,实际开发中,我们的数据源通常不会是某一个现成控件的属性,多半是xml/数据库等对应的实体类,这里要注意的是,如果控件与自定义类绑定,自定义类必须实现INotifyPropertyChanged接口,参考下面的代码:

 

  public   class  Test : INotifyPropertyChanged
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif    
{
        
public event PropertyChangedEventHandler PropertyChanged;

        
private double _width;

        
public double Width
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
set
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                _width 
= value;
                
if (PropertyChanged != null
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif                
{
                    PropertyChanged(
thisnew PropertyChangedEventArgs("Width"));
                }

            }


            
get
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
return _width;
            }

        }

    }

 

绑定示例代码:

Binding bindwidth  =   new  Binding( " Width " );
bindwidth.Mode 
=  BindingMode.OneTime;
this .rect.SetBinding(UserControl.WidthProperty, bindwidth);
Test t 
=   new  Test();
t.Width
= 100 ;
this .rect.DataContext  =  t; 

 

转载请注明来自菩提树下的杨过

原文地址:http://www.cnblogs.com/yjmyzz/archive/2009/11/09/1599058.html 

最后给出文中源码下载:http://files.cnblogs.com/yjmyzz/BindingStudy.rar

目录
相关文章
Silverlight 游戏开发小技“.NET研究”巧:昼夜交替动画
  记得在WP7上玩一个游戏有段动画很有趣,是背景在进行昼夜交替,一会儿白天太阳出来白天了,一会儿月亮蹦出来夜晚了,在以前做C++程序的时候曾经实现过类似的效果,今天早上移植了一下到Silverlight当中效果还是不错,当然了,有了Blend神器,就完全不用通过代码的方式实现,真的方便了很多。
1087 0
|
Web App开发 Windows
你应该知道“.NET研究”的15个Silverlight诀窍
  我热爱Silverlight,并且身体力行写了很多Silverlight程序,也讨论了很多关于Silverlight的技术。对于刚刚接触Silverlight的开发人员来说,这篇文章是最适合你的。这篇文章列出了我使用Silverlight进行开发后,发现的15条小诀窍。
983 0
Silverlight 游“.NET研究”戏开发小技巧:扇形排列元素
  斗地主风靡了大江南北,在春晚都做免费性推广,棋牌游戏平台几乎将其作为标配,但是牌类游戏总是一成不变的样子——横向排列,如果扇形排列应该更加符合真实,最近在WP7上玩了一个UNO游戏就是用扇形排列,感觉很不错,今天咱们照猫画虎,在Silverlight上实现一个扇形的手牌效果。
974 0
Silverlight 游戏开发小技“.NET研究”巧:动感弹出动画
  玩Silverlight的朋友一定对自带控件ChildWindow印象深刻,Show的时候仿佛从远处弹了出来,这个效果制作起来并不复杂,下面就将介绍这个小技巧,本篇并非是一个新鲜的技巧,而是一般的故事板结合变换放缩实现。
843 0

热门文章

最新文章