2010-04-14 4 views
4

Silverlight에서 INotifyPropertyChanged를 사전에 바인딩 할 때와 같이 작동시키지 못합니다. 아래 예제에서는 페이지가 사전에 바인딩되지만 괜찮 았지만 텍스트 상자 중 하나의 내용을 변경하면 CustomProperties 속성 설정자가 호출되지 않습니다. CustomProperties 속성 setter는 CustomProperties가 설정된 경우에만 호출되며 내부의 값이 설정되지 않은 경우에는 호출됩니다. 사전 값에 대한 일부 유효성 검사를 시도하고 있으므로 사전 내의 각 값이 변경 될 때 일부 코드를 실행하려고합니다. 내가 여기서 할 수있는 일이 있니?Silverlight에서 INotifyPropertyChanged를 사용하여 사전에 바인딩

C 번호

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}" /> 

답변

6

컬렉션 데이터 바인딩을 지원하기 INotifyPropertyChanged interface 외에 INotifyCollectionChanged interface을 구현해야

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. ObservableCollection class은 List-like 컬렉션을 구현하기 위해 구현하지만, .NET Framework에는 이와 같은 사전 같은 컬렉션이 없다고 생각합니다. 당신 스스로 그것을 구현해야 할 가능성이 있습니다.

+0

감사합니다. 나는 wpf의 ObservableDictionary 구현을 tweeked tweeked : http://drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/ –

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)); 
    } 
} 

MainPage : -

public MainPage() 
    { 
     InitializeComponent(); 

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

     this.DataContext = ent; 

    } 

MainPage 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에 알림이 표시됩니다.

관련 문제