Silverlight实用窍门系列:47.Silverlight中元素到元素的绑定,以及ObservableCollection和List的使用区别
问题一:在某一些情况下,我们使用MVVM模式的时候,对于某一个字段(AgeField)需要在前台的很多个控件(A、B、C、D、E)进行绑定,但是如何能够让我们后台字段名改变的时候能够非常方便的改变所有使用了这个字段的控件呢?
回答:使用Element to Element Binding,将AgeFiled绑定到A控件,然后再让B、C、D、E控件绑定A控件的使用AgeField字段的属性。
例如:字段(AgeField)的数据是年龄大小,A、B、C、D、E控件分别是Ellipse、Label、Slider、TextBox、ProgressBar,这些字段的Width、Value或者Text值按照常规的做法,这几个控件都是在MVVM模式下都是绑定的AgeField。但是这个字段名在后期代码维护的时候修改为Age了,我们就不得不需要一一修改五个控件的绑定值。如果这几个控件还分布在不同位置,那么寻找起来就将更加麻烦。那么这里我们就将使用到Silverlight 3的一个新特性Element to Element Binding。
实例一:我们在这里有一个TextBox控件tbAge,其Value值假定绑定到某一个字段,然后我们再添加Slider、ProgressBar、Ellipse控件,使用Value="{Binding Text,ElementName=tbAge,Mode=TwoWay}"这样的方式将tbAge的Text值绑定到这几个控件上。下面我们看源码如下:
<!--这里是数据源--> <TextBox x:Name="tbAge" Text="30" Width="80" Margin="0,87,0,183" Height="30" HorizontalAlignment="Left" VerticalAlignment="Top"/> <!--Silder控件绑定上面的tbAge控件的值--> <Slider Name="sdAge" Value="{Binding ElementName=tbAge, Path=Text, Mode=TwoWay }" Minimum="1" Maximum="100" Height="40" Width="210" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,145,0,115"></Slider> <!--ProgressBar控件绑定上面的tbAge控件的值--> <ProgressBar Value="{Binding Text,ElementName=tbAge,Mode=TwoWay}" Margin="0,27,0,0" Name="progressBar1" Height="24" HorizontalAlignment="Left" VerticalAlignment="Top" Width="210" /> <!--Ellipse的Width属性绑定sdAge控件的值--> <Ellipse Width="{Binding Value,ElementName=sdAge,Mode=TwoWay}" Height="100" HorizontalAlignment="Left" Margin="0,200,0,0" Name="ellipse1" Stroke="Black" StrokeThickness="1" VerticalAlignment="Top" />
问题二:为什么在Silverlight中我们更常用ObservableCollection<T>来作为数据集合绑定到控件中,而不是使用List<T>呢?
回答:当T继承于INotifyPropertyChanged接口的时候,如果T的属性值发生变化时,ObservableCollection和List都能够让前台UI发生相应的改变。但是当增加一个T的数据行时,List不能及时更新前台UI,而ObservableCollection能够将新增的T数据行马上更新到UI上去。
实例二:我们拖出两个DataGrid控件分别是ShowListCity和ShowObservableCity,然后分别绑定数据List和Observable数据,再添加一个按钮为这两个数据集合添加集合值。看UI是否变化。下面我们看源码如下:
<sdk:DataGrid HorizontalAlignment="Left" AutoGenerateColumns="False" Margin="476,12,0,0" Name="ShowListCity" VerticalAlignment="Top" Height="169" Width="324" > <sdk:DataGrid.Columns> <sdk:DataGridTextColumn Header="省会" Binding="{Binding AddrName}" IsReadOnly="True" Width="108"/> <sdk:DataGridTextColumn Header="城市" Binding="{Binding CityName}" IsReadOnly="True" Width="108"/> <sdk:DataGridTextColumn Header="电话区号" Binding="{Binding TelNum}" IsReadOnly="True" Width="108"/> </sdk:DataGrid.Columns> </sdk:DataGrid> <sdk:DataGrid HorizontalAlignment="Left" AutoGenerateColumns="False" Margin="476,187,0,0" Name="ShowObservableCity" VerticalAlignment="Top" Height="180" Width="324" > <sdk:DataGrid.Columns> <sdk:DataGridTextColumn Header="省会" Binding="{Binding AddrName}" IsReadOnly="True" Width="108"/> <sdk:DataGridTextColumn Header="城市" Binding="{Binding CityName}" IsReadOnly="True" Width="108"/> <sdk:DataGridTextColumn Header="电话区号" Binding="{Binding TelNum}" IsReadOnly="True" Width="108"/> </sdk:DataGrid.Columns> </sdk:DataGrid> <Button Content="添加条目" Height="23" HorizontalAlignment="Left" Margin="364,13,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
下面是MainPage.xaml.cs代码
public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); ListCity = new List<CityInformation>() { new CityInformation(){ AddrName="四川", CityName="成都", TelNum="028"}, new CityInformation(){ AddrName="北京", CityName="北京", TelNum="010"}, new CityInformation(){ AddrName="广东", CityName="广州", TelNum="021"} }; ObservableCity = new ObservableCollection<CityInformation>() { new CityInformation(){ AddrName="四川", CityName="成都", TelNum="028"}, new CityInformation(){ AddrName="北京", CityName="北京", TelNum="010"}, new CityInformation(){ AddrName="广东", CityName="广州", TelNum="021"} }; this.ShowListCity.ItemsSource = ListCity; this.ShowObservableCity.ItemsSource = ObservableCity; } private List<CityInformation> _ListCity; /// <summary> /// 城市集合 /// </summary> public List<CityInformation> ListCity { get { return _ListCity; } set { _ListCity = value; } } private ObservableCollection<CityInformation> _ObservableCity; /// <summary> /// 城市集合 /// </summary> public ObservableCollection<CityInformation> ObservableCity { get { return _ObservableCity; } set { _ObservableCity = value; } } private void button1_Click(object sender, RoutedEventArgs e) { ListCity.Add(new CityInformation() { AddrName = "重庆", CityName = "重庆", TelNum = "022" }); ObservableCity.Add(new CityInformation() { AddrName = "重庆", CityName = "重庆", TelNum = "022" }); } }
下面我们来看CityInformation实例类代码如下:
/// <summary> /// 城市信息的实体类 /// </summary> public class CityInformation { private string _AddrName; private string _CityName; private string _TelNum; /// <summary> /// 地址名 /// </summary> public string AddrName { get { return _AddrName; } set { _AddrName = value; } } /// <summary> /// 城市名 /// </summary> public string CityName { get { return _CityName; } set { _CityName = value; } } /// <summary> /// 区号 /// </summary> public string TelNum { get { return _TelNum; } set { _TelNum = value; } } }