案例分析Silverlight中的Binding技术
在WPF(Windows Presentation Foundation)中,提供了数据的binding技术,使显示和交互数据变得简单,并与数据的管理独立。Data binding可以同步两个不同对象的两个属性值。例如,我们需要在界面上显示一个内容动态变化的文本框,我们可以建立一个binding对象,把文本框的值和一个变量绑定,这样每次修改这个变量或者修改文本框的值时,另一端的内容就可以自动同步。在Silverlight中,由于XAML这种标记语言的运用,使得binding变得更加简单了。只需要用简短的一个属性值就可以定义一个binding。
为了更形象一点,我们还是用一个例子来深入binding技术。假设现在在联网游戏对战平台中,需要一个文本标签,显示我方的人数。此外还有一个列表,显示一个服务器上的所有在线玩家。大体界面如下图所示:
现在我们假设游戏后台有一个Game类,其中包含了我方人数、在线玩家的信息,这些数据由其他模块提供。我们需要将它们独立于数据管理部分显示出来。
先看看我方玩家数目的显示,为简化问题,假设Game类中有一个整型变量:
1 | public int TeammateCount; |
存储了表示我方人数的字符串。为了实现binding,首先必须让Game类继承INotifyPropertyChanged接口,此接口提供了PropertyChanged事件。
1 2 3 4 5 6 | public class Game : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; // Bla bla bla } |
接下来,需要在TeammateCount的值发生改变的时候,触发这一事件。因此要改变TeammateCount属性set方法的行为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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)); } } |
1 2 | < sdk:Label Name="lblTeammateCount" Content="{Binding TeammateCount}" /> |
1 | |
1 2 3 4 5 6 7 | Game game = new Game(); public MainPage() { InitializeComponent(); lblTeammateCount.DataContext = game; } |
在Test按钮中加一小段代码测试一下
1 2 3 4 | private void btnTest_Click( object sender, RoutedEventArgs e) { game.TeammateCount = 123; } |
点击按钮之后,发现显示的结果立刻发生了变化,我们的第一个小实验圆满结束。
下面我们来增加问题的难度,更深入地学习binding。假设现在我们并不是直接输出人数的阿拉伯数字形式,而是逐位转换成汉字呢?这时,就需要借助binding的数据转换(Data Conversions)了。为了实现转换,我们需要定义一个继承IValueConverter接口的类 NumberConverter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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的代码:
1 2 3 | < UserControl.Resources > < local:NumberConverter x:Key="numberConverter" /> </ UserControl.Resources > |
1 2 | < sdk:Label Name="lblTeammateCount" Content="{Binding TeammateCount, Converter={StaticResource numberConverter}}" /> |
如此即可实现带有数据转换的binding。
作为最后一个例子,我们来看看如何把Listbox的内容binding到一个Collection。Silverlight中已经实现了一个ObservableCollection类,继承了INotifyCollectionChanged接口,当Collection的内容发生改变时,自动触发CollectionChanged事件。因此,我们不需要像上面一样专门写一个类,直接使用现成的就可以了。
首先,需要定义玩家的数据类型:
1 2 3 4 5 6 7 8 9 10 11 | 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成员:
1 | public ObservableCollection<Player> Players; |
修改界面中ListBox的定义:
1 2 3 4 5 6 7 8 9 10 11 | < 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到什么路径的信息。
然后在主界面的构造函数中添加:
1 | lstPlayers.ItemsSource = game.Players; |
指定ListBox的数据源。如此即可完成整个Collection的binding过程,当Players发生改变时,界面显示也会改变。
菜鸟初学Silverlight,还望高手多多指教!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库