2011-11-17 4 views
1

최대한 최선을 다해 검색했으며이 특정 문제에 대한 답변을 찾을 수 없습니다. WPF 바인딩이있는 것 같습니다. 위대하고 모두,하지만 결국 벽에 머리를 두드리는 소리가납니다.ObservableCollection 내부 클래스의 속성에 양방향 WPF 바인딩

Imports System.ComponentModel 
Imports System.Collections.ObjectModel 

Public Class AmandaSeyfried 
    Implements INotifyPropertyChanged 

    Shared _config As New config 

    Public Event PropertyChanged(sender As Object, E As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged 

    Protected Overridable Sub OnPropertyChanged(propertyName As String) 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) 
    End Sub 

    Private Shared _thisInstance As AmandaSeyfried 

    Protected Sub New() 
     ' initialization goes here 
    End Sub 

    Public Shared Function GetSingleton() As AmandaSeyfried 
     ' initialize object if it hasn't already been done 
     If _thisInstance Is Nothing Then 
      _thisInstance = New AmandaSeyfried 
     End If 

     ' return the initialized instance 
     Return _thisInstance 
    End Function 

    Public Class CountryTranslation 
     Implements INotifyPropertyChanged 

     Private Property _englishCountryName As String = "" 
     Public Property EnglishCountryName As String 
      Get 
       Return _EnglishCountryName 
      End Get 
      Set(value As String) 
       If _englishCountryName <> value Then 
        _englishCountryName = value 
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("EnglishCountryName")) 
       End If 
      End Set 
     End Property 

     Private Property _foreignCountryName As String = "" 
     Public Property ForeignCountryName As String 
      Get 
       Return _foreignCountryName 
      End Get 
      Set(value As String) 
       If _foreignCountryName <> value Then 
        _foreignCountryName = value 
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("ForeignCountryName")) 
       End If 
      End Set 
     End Property 

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

    Private WithEvents _countryTranslations As New ObservableCollection(Of CountryTranslation) 
    Public Property CountryTranslations As ObservableCollection(Of CountryTranslation) 
     Get 
      If _config.GetKeyTextValue("countryTranslations") <> "" Then 
       Dim reader As New IO.StringReader(_config.GetKeyTextValue("countryTranslations")) 
       Dim Serializer As New Xml.Serialization.XmlSerializer(_countryTranslations.GetType) 
       _countryTranslations = Serializer.Deserialize(reader) 
      End If 

      Return _countryTranslations 
     End Get 
     Set(value As ObservableCollection(Of CountryTranslation)) 
      _countryTranslations = value 
      RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("CountryTranslations")) 
     End Set 
    End Property 

    Private Sub CountryTranslationCollectionChanged(sender As Object, e As Specialized.NotifyCollectionChangedEventArgs) Handles _countryTranslations.CollectionChanged 
     Dim newStringWriter As New IO.StringWriter 
     Dim NewSerializer As New Xml.Serialization.XmlSerializer(_countryTranslations.GetType) 
     NewSerializer.Serialize(newStringWriter, _countryTranslations) 
     _config.SaveKeyTextValue("countryTranslations", newStringWriter.ToString) 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("CountryTranslations")) 
    End Sub 

End Class 

_config 로컬 SQLCE 인스턴스에서 데이터를 검색하는 상점과 이름이 잘못 도우미 클래스입니다 : 좋아

, 나는 결국 내가 바인딩있어 하나 인 싱글 톤 클래스가 있습니다. 본질적으로 객체는 직렬화되고 DB에 저장되며 필요할 때마다 DB에서 꺼내어 객체로 역 직렬화됩니다. 대체로, 그것은 꽤 잘 작동하고있는 것 같습니다.

내 문제는 개체에 바인딩 할 수 있지만 CollectionChangedMethod 처리기를 통해 WPF DataGrid에 행이 추가 될 때 모니터링 할 수 있지만 CountryTranslation의 두 속성 중 하나가 변경되었습니다.

나머지 관련 코드는 ... XAML ... 분명히 많지만 바인딩의 XAML 부분이 잘못되었다고 생각하지 않으므로 관련성이있는 부분으로 잘라냅니다.

<toolkit:DataGrid Margin="12,12,12,12" ItemsSource="{Binding Path=KarenSmith.CountryTranslations, Mode=TwoWay}" AutoGenerateColumns="False" HorizontalAlignment="Stretch" Width="Auto" SelectionMode="Single"> 
    <toolkit:DataGrid.Columns> 
     <toolkit:DataGridTextColumn Width="283" Binding="{Binding EnglishCountryName,Mode=TwoWay}" /> 
     <toolkit:DataGridTextColumn Width="283" Binding="{Binding ForeignCountryName,Mode=TwoWay}" /> 
    </toolkit:DataGrid.Columns> 
</toolkit:DataGrid> 

그리고 좋은 간단한 코드 숨김 : 나는이 게터와 CountryTranslation 클래스의 세터에 약간의 브레이크 포인트가 발생하는 경우들이 데이터 그리드를 통해 (변경되는 때

Public Class Preferences 

    Public Property KarenSmith As AmandaSeyfried = AmandaSeyfried.GetSingleton 

    Sub New() 

     ' This call is required by the designer. 
     InitializeComponent() 

     ' Add any initialization after the InitializeComponent() call. 
     DataContext = Me 

    End Sub 

    Private Sub Close_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) 
     Me.Close() 
    End Sub 
End Class 

, 나는 모니터링 할 수 있습니다 , 바인딩이 작동 중입니다.)하지만 시도해 보겠습니다. 메인 클래스에서 다시 데이터 저장소를 업데이트하여 변경 사항을 표시합니다.

+0

CollectionChanged가 발생 여기

은 예입니다 컬렉션이 변경되면 (컬렉션 내의 항목의 속성이 아님) 국가 이름 속성 내의 데이터 저장소도 업데이트하십시오. –

답변

2

보통 에 이벤트를 추가합니다.이 이벤트는 추가 될 때 PropertyChanged 이벤트를 첨부하고 이벤트 리스너는 변경 사항을 수신하고 필요에 따라 이벤트를 처리합니다.

Public Sub New() 
    AddHandler MyCollection.CollectionChanged, AddressOf MyCollection_CollectionChanged 
End Sub 

Private Sub MyCollection_CollectionChanged(sender As Object, e As CollectionChangedEventArgs) 
    If e.NewItems IsNot Nothing Then 
     For Each item As MyItem In e.NewItems 
      AddHandler item.PropertyChanged, AddressOf MyItem_PropertyChanged 
     Next 
    End If 

    If e.OldItems IsNot Nothing Then 
     For Each item As MyItem In e.OldItems 
      RemoveHandler item.PropertyChanged, AddressOf MyItem_PropertyChanged 
     Next 
    End If 
End Sub 

Private Sub MyItem_PropertyChanged(sender As Object, e As PropertyChangedEventArgs) 
    If e.PropertyName = "Some Property" Then 
     DoWork() 
    End If 
End Sub 

는 C# 버전은 다음과 같습니다 (난 그냥 VB.Net 변환기에 C#을 통해 그것을 실행하기 때문에 구문이 올바른지 희망) :

public MyViewModel() 
{ 
    MyCollection.CollectionChanged += MyCollection_CollectionChanged; 
} 

void MyCollection_CollectionChanged(object sender, CollectionChangedEventArgs e) 
{ 
    if (e.NewItems != null) 
     foreach(MyItem item in e.NewItems) 
      item.PropertyChanged += MyItem_PropertyChanged; 

    if (e.OldItems != null) 
     foreach(MyItem item in e.OldItems) 
      item.PropertyChanged -= MyItem_PropertyChanged; 
} 

void MyItem_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "Some Property") 
     DoWork(); 
} 
+0

고마워요! 이로써 Observable Collection의 항목에 이벤트 처리기를 추가하는 방법을 알게되었습니다. 굉장해. –

관련 문제