在WPF(Windows Presentation Foundation)中,提供了数据的binding技术,使显示和交互数据变得简单,并与数据的管理独立。Data binding可以同步两个不同对象的两个属性值。例如,我们需要在界面上显示一个内容动态变化的文本框,我们可以建立一个binding对象,把文本框的值和一个变量绑定,这样每次修改这个变量或者修改文本框的值时,另一端的内容就可以自动同步。在Silverlight中,由于XAML这种标记语言的运用,使得binding变得更加简单了。只需要用简短的一个属性值就可以定义一个binding。
为了更形象一点,我们还是用一个例子来深入binding技术。假设现在在联网游戏对战平台中,需要一个文本标签,显示我方的人数。此外还有一个列表,显示一个服务器上的所有在线玩家。大体界面如下图所示:
现在我们假设游戏后台有一个Game类,其中包含了我方人数、在线玩家的信息,这些数据由其他模块提供。我们需要将它们独立于数据管理部分显示出来。
先看看我方玩家数目的显示,为简化问题,假设Game类中有一个整型变量:
public int TeammateCount;
存储了表示我方人数的字符串。为了实现binding,首先必须让Game类继承INotifyPropertyChanged接口,此接口提供了PropertyChanged事件。
public class Game : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// Bla bla bla
}
接下来,需要在TeammateCount的值发生改变的时候,触发这一事件。因此要改变TeammateCount属性set方法的行为:
private int _TeammateCount;
public int TeammateCount
{
get { return _TeammateCount; }
set
{
_TeammateCount = value;
NotifyPropertyChanged("TeammateCount");
}
}
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
<sdk:Label Name="lblTeammateCount"
Content="{Binding TeammateCount}" />
Game game = new Game();
public MainPage()
{
InitializeComponent();
lblTeammateCount.DataContext = game;
}
在Test按钮中加一小段代码测试一下
private void btnTest_Click(object sender, RoutedEventArgs e)
{
game.TeammateCount = 123;
}
点击按钮之后,发现显示的结果立刻发生了变化,我们的第一个小实验圆满结束。
下面我们来增加问题的难度,更深入地学习binding。假设现在我们并不是直接输出人数的阿拉伯数字形式,而是逐位转换成汉字呢?这时,就需要借助binding的数据转换(Data Conversions)了。为了实现转换,我们需要定义一个继承IValueConverter接口的类 NumberConverter:
public class NumberConverter : IValueConverter
{
static String zhNum = "〇一二三四五六七八九";
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
String s = "";
foreach (Char c in value.ToString())
if (c >= '0' && c <= '9')
s += zhNum[c - '0'];
return s;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
然后,再界面的XAML中加入相应实现binding converter的代码:
<UserControl.Resources>
<local:NumberConverter x:Key="numberConverter" />
</UserControl.Resources>
<sdk:Label Name="lblTeammateCount"
Content="{Binding TeammateCount, Converter={StaticResource numberConverter}}" />
如此即可实现带有数据转换的binding。
作为最后一个例子,我们来看看如何把Listbox的内容binding到一个Collection。Silverlight中已经实现了一个ObservableCollection类,继承了INotifyCollectionChanged接口,当Collection的内容发生改变时,自动触发CollectionChanged事件。因此,我们不需要像上面一样专门写一个类,直接使用现成的就可以了。
首先,需要定义玩家的数据类型:
public class Player
{
public int ID { get; set; }
public String Name { get; set; }
public Player(int id, String name)
{
ID = id;
Name = name;
}
}
注意这里必须要为成员定义public的get方法,否则binding会失败。
接下来,在Game类中添加Players成员:
public ObservableCollection<Player> Players;
修改界面中ListBox的定义:
<ListBox Name="lstPlayers">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ID}" />
<TextBlock Text="," />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
这里定义了ListBox中每个Item的显示方式,bind到什么路径的信息。
然后在主界面的构造函数中添加:
lstPlayers.ItemsSource = game.Players;
指定ListBox的数据源。如此即可完成整个Collection的binding过程,当Players发生改变时,界面显示也会改变。
菜鸟初学Silverlight,还望高手多多指教!
转载于:https://www.cnblogs.com/OMG-Team/archive/2011/09/06/2169119.html