Silverlight 通过索引器绑定动态数据
绑定动态数据是做 Silverlight 程序时经常会遇到的问题。本文介绍 Silverlight 通过绑定索引器实现绑定动态数据,即在设计时不知道数据的结构,如在设计时不知道要绑定的类有哪些属性。
绑定索引器是 Silverlight 4 新增的特性,这一特性使用我们可以在设计时不必知道要绑定的类有哪些属性,但是还可以绑定。下面先看一下如何绑定索引器。
<TextBox Grid.Row="0" Height="23" Width="148" HorizontalAlignment="Center" VerticalAlignment="Center" Name="txtName" Text="{Binding Path=[name]}" /> <TextBox Grid.Row="1" Height="23" Width="148" HorizontalAlignment="Center" VerticalAlignment="Center" Name="txtAge" Text="{Binding Path=[age]}" />
绑定索引器的语法和通常绑定数据的语法非常相似,格式为:Binding="{Binding Path=[Key]}" 。下面新建一个要绑定的 Person 类,并添加一个索引器,完整的代码如下:
public class Person : INotifyPropertyChanged { private Dictionary<string, object> data = new Dictionary<string, object>(); public object this[string key] { get { if (!data.ContainsKey(key)) data[key] = null; return data[key]; } set { data[key] = value; NotifyPropertyChanged(""); } } public string[] Keys { get { return data.Keys.ToArray(); } } public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
下面新建一个 Person 类的实例,并绑定到第一段代码创建的两个TextBox上面。
Person person = new Person(); person["name"] = "avatar"; person["age"] = 123456; LayoutRoot.DataContext = person;
运行结果如下:
上面的代码将索引器的参数名直接写在代码中了,如果在设计时不知道类的结构,上面的代码依然无法解决问题。我们可以通过下面的代码轻松解决这个问题:
Person person = new Person(); person["name"] = "avatar"; person["age"] = 123456; LayoutRoot.DataContext = person; for (int i = 0; i < person.Keys.Length; i++) { TextBox txt = new TextBox() { Width = 200, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; Binding binding = new Binding("[" + person.Keys[i] + "]") { Mode = BindingMode.TwoWay }; txt.SetBinding(TextBox.TextProperty, binding); txt.SetValue(Grid.RowProperty, i); LayoutRoot.Children.Add(txt); }
这段代码的运行结果和上面的代码的运行结果完全一样。
以上讲的是通过索引器将单个类绑定到 Silverlight 控制上,如果要将包含多个类的列表绑定到 DataGrid 上呢?这个问题我们可以通过类似的方式轻松解决。下面是将多个类的列表绑定到 DataGrid 上的代码:
private List<Person> lst = new List<Person>();
Person person1 = new Person(); person1["name"] = "Avatar"; person1["age"] = 52342; Person person2 = new Person(); person2["name"] = "Harry Potter"; person2["age"] = 33432; lst.Add(person1); lst.Add(person2); string[] headers = person1.Keys; for (int i = 0; i < headers.Length; i++) { dataGrid1.Columns.Add(new DataGridTextColumn() { Header = headers[i], CanUserSort = true, IsReadOnly = false, Binding = new Binding("[" + headers[i] + "]") { Mode = BindingMode.TwoWay } }); } dataGrid1.ItemsSource = lst;
注意:如果想让用户可以点击表头排序,需要设置系列的 CanUserSort = true 。运行结果如下图:
如果需要显示 Person 类的性别,只需在上面的代码中添加:person1["gender"] = "男"; person2["gender"] = "男"; 就可以实现,运行结果如下:
示例代码下载:SLBindingDynamicObject.7z