在Silverlight中使用INotifyPropertyChanged绑定字典

4
在Silverlight中,当绑定到字典时,我无法使INotifyPropertyChanged按照我的意愿工作。在下面的示例中,页面可以绑定到字典,但是当我更改其中一个文本框的内容时,CustomProperties属性的setter方法不会被调用。只有在设置CustomProperties时才会调用CustomProperties属性的setter方法,而不是在其中的值被设置时。我试图对字典值进行一些验证,因此希望在每个字典值更改时运行一些代码。这里我能做些什么吗?
public partial class MainPage : UserControl
{

    public MainPage()
    {
        InitializeComponent();

        MyEntity ent = new MyEntity();
        ent.CustomProperties.Add("Title", "Mr");
        ent.CustomProperties.Add("FirstName", "John");
        ent.CustomProperties.Add("Name", "Smith");

        this.DataContext = ent;
    }

}

public class MyEntity : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler System.ComponentModel.INotifyPropertyChanged.PropertyChanged;
    public delegate void PropertyChangedEventHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e);

    private Dictionary<string, object> _customProps;
    public Dictionary<string, object> CustomProperties {
        get {
            if (_customProps == null) {
                _customProps = new Dictionary<string, object>();
            }
            return _customProps;
        }
        set {
            _customProps = value;
            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs("CustomProperties"));
            }
        }
    }

}

VB

Partial Public Class MainPage
    Inherits UserControl

    Public Sub New()
        InitializeComponent()

        Dim ent As New MyEntity
        ent.CustomProperties.Add("Title", "Mr")
        ent.CustomProperties.Add("FirstName", "John")
        ent.CustomProperties.Add("Name", "Smith")

        Me.DataContext = ent
    End Sub

End Class

Public Class MyEntity
    Implements INotifyPropertyChanged

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Private _customProps As Dictionary(Of String, Object)
    Public Property CustomProperties As Dictionary(Of String, Object)
        Get
            If _customProps Is Nothing Then
                _customProps = New Dictionary(Of String, Object)
            End If
            Return _customProps
        End Get
        Set(ByVal value As Dictionary(Of String, Object))
            _customProps = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("CustomProperties"))
        End Set
    End Property

End Class

Xaml

<TextBox Height="23" Name="TextBox1" Text="{Binding Path=CustomProperties[Title], Mode=TwoWay}" />
<TextBox Height="23" Name="TextBox2" Text="{Binding Path=CustomProperties[FirstName], Mode=TwoWay}" />
<TextBox Height="23" Name="TextBox3" Text="{Binding Path=CustomProperties[Name], Mode=TwoWay}" />
2个回答

8

这里提供一种(有些简化)的解决方案。

public class MyEntity : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    private readonly Dictionary<string, object> _customProps = new Dictionary<string, object>();

    public void AddCustomProperty(string key, object value)
    {
        _customProps.Add(key, value);
    }

    public object this[string key]
    {
        get { return _customProps[key]; }
        set
        {
            // The validation code of which you speak here.
            _customProps[key] = value;
            NotifyPropertyChanged("Item[" + key "]");
        }
    }

    private void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}

主页:

    public MainPage()
    {
        InitializeComponent();

        MyEntity ent = new MyEntity();
        ent.AddCustomProperty("Title", "Mr");
        ent.AddCustomProperty("FirstName", "John");
        ent.AddCustomProperty("Name", "Smith");

        this.DataContext = ent;

    }

主页 Xaml:

        <TextBox Height="23" Name="TextBox1" Text="{Binding [Title], Mode=TwoWay}" />
        <TextBox Height="23" Name="TextBox2" Text="{Binding [FirstName], Mode=TwoWay}" />
        <TextBox Height="23" Name="TextBox3" Text="{Binding [Name], Mode=TwoWay}" />

您的问题中重要的是,您的代码涉及将属性值分配到字典中。最初,您的代码公开了Dictionary,所有的赋值工作都通过框架组件代码完成。在这个版本中,MyEntity有一个字符串索引器,直接分配自定义属性,并且Dictionary被设置为私有。
请注意,实现INotifyPropertyChanged并不是回答您具体问题的必要条件,但我认为您会需要它。例如,如果您重新分配一个新值给自定义属性,您希望UI得到通知。

6

谢谢,我调整了 dr wpf 的 ObservableDictionary 实现:http://drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/ - Carl Rippon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接