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

posted @ 2011-06-18 00:13  forgetu  阅读(1873)  评论(6编辑  收藏  举报