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
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void rboMode_OneTime_Checked(object sender, RoutedEventArgs e)
{
if (rect != null)
{
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)
{
if (rect != null)
{
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)
{
if (rect != null)
{
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)
{
if (rect != null)
{
rect.Width += 5;
}
}
private void btnWidthSub_Click(object sender, System.Windows.RoutedEventArgs e)
{
if (rect != null)
{
rect.Width -= 5;
}
}
}
}
代码不复杂,基本功能就是让绑定模式可以自由切换,相信大家一看就明白
这回我们来测试一下OneWay模式,运行后选择OneWay模式,然后再手动拖动滑块,会发现矩形的宽度随着滑块的值不断变化,即OneWay模式下,数据源的变化会自动反应在绑定的目标控件上,继续,我们点击最下面的二个按钮,改变矩形的宽度,发现滑块不会自己移动,这说明了OneWay模式下控件的属性变化,不会反过来影响数据源本身。
最后切换到TwoWay模式,与OneWay模式的不同之外在于,如果我们点击最下面的按钮,改变矩形的宽度,会发现滑块自己移动了,移动后的值即为矩形的宽度,结论:TwoWay模式下,控件与数据源任何一方的变化都会影响对另一方。(个人感觉这个功能很NB,如果我们自己实现的话,不知道要写多少行代码!)
当然,实际开发中,我们的数据源通常不会是某一个现成控件的属性,多半是xml/数据库等对应的实体类,这里要注意的是,如果控件与自定义类绑定,自定义类必须实现INotifyPropertyChanged接口,参考下面的代码:
public
class
Test : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private double _width;
public double Width
{
set
{
_width = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Width"));
}
}
get
{
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