2013-10-18 91 views
1

使用VS 2102,.NET 4.0和MVVM Light。WPF:OnCollectionChanged沒有觸發

我有以下代碼,將XML文件中的項目讀入ObservableCollection。然後,如果集合更改(使用IsDirty標誌)但OnCodeCollectionChanged方法未被執行,則需要使用Converter更新Save按鈕。

集合已正確顯示在數據網格中,我可以將新條目添加到數據網格,但OnCodeCollectionChanged方法永遠不會被調用。我不是想要捕獲現有項目的更改(我知道ObservableCollection不會通知該更改),我只是想在更改事件時添加或刪除新項目。

我在做什麼錯,是否有更好的方式做我想做的事?

Codes.cs(型號)

[Serializable()] 
public class Codes 
{ 
    public Codes() { } 

    [XmlElement("Code")] 
    public ObservableCollection<Code> CodeCollection { get; set; } 

} 

[Serializable()] 
public class Code 
{ 
    [XmlElement("AccpacCode")] 
    public string AccpacCode { get; set; } 

    [XmlElement("LAC")] 
    public string LAC { get; set; } 

    [XmlElement("SCSCode")] 
    public string SCSCode { get; set; } 

    [XmlElement("ParentEmployerAccpacCode")] 
    public string ParentEmployerAccpacCode { get; set; } 
} 

MainViewMdoel.cs(視圖模型)

public class MainViewModel : ViewModelBase 
{ 
    public bool IsDirty = false; 

    /// <summary> 
    /// ObservableCollection of Codes 
    /// </summary> 
    private const string CodeCollectionPropertyName = "CodeCollection"; 
    private ObservableCollection<Code> _codeCollection; 
    public ObservableCollection<Code> CodeCollection 
    { 
     get 
     { 
      if (_codeCollection == null) 
      { 
       _codeCollection = new ObservableCollection<Code>(); 
      } 
      return _codeCollection; 
     } 
     set 
     { 
      if (_codeCollection == value) 
      { 
       return; 
      } 

      _codeCollection = value; 
      RaisePropertyChanged(CodeCollectionPropertyName); 
     } 
    } 

    /// <summary> 
    /// Initializes a new instance of the MainViewModel class. 
    /// </summary> 
    public MainViewModel(IDataService dataService) 
    { 
     // Change notification setup 
     CodeCollection.CollectionChanged += OnCodeCollectionChanged; 

     // Load XML file into ObservableCollection 
     LoadXML(); 
    } 

    private void LoadXML() 
    { 
     try 
     { 
      XmlSerializer _serializer = new XmlSerializer(typeof(Codes)); 

      // A file stream is used to read the XML file into the ObservableCollection 
      using (StreamReader _reader = new StreamReader(@"LocalCodes.xml")) 
      { 
       CodeCollection = (_serializer.Deserialize(_reader) as Codes).CodeCollection; 

      }     
     } 
     catch (Exception ex) 
     { 
      // Catch exceptions here 
     } 

    } 

    private void SaveToXML() 
    { 
     try 
     { 

     } 
     catch (Exception ex) 
     { 

     } 
    } 

    private RelayCommand<ViewModelBase> _saveButtonClickedCommand; 
    public RelayCommand<ViewModelBase> SaveButtonClickedCommand; 
    private void SaveButtonClicked(ViewModelBase viewModel) 
    { 
     SaveToXML(); 
    } 

    private void OnCodeCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     IsDirty = true; 
    } 
} 

MainWindow.xaml(查看)

<Window.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <ResourceDictionary Source="Skins/MainSkin.xaml" /> 
     </ResourceDictionary.MergedDictionaries> 

     <conv:IsDirtyConverter x:Key="IsDirtyConverter" /> 

    </ResourceDictionary> 
</Window.Resources> 

<Grid x:Name="LayoutRoot"> 

    <TextBlock FontSize="36" 
       FontWeight="Bold" 
       Foreground="Purple" 
       Text="{Binding WelcomeTitle}" 
       VerticalAlignment="Top" 
       TextWrapping="Wrap" Margin="10,10,10,0" Height="54" HorizontalAlignment="Center" /> 

    <DataGrid Margin="10,69,10,38" 
       ItemsSource="{Binding CodeCollection}"/> 
    <Button Name="SaveButton" Content="Save" HorizontalAlignment="Right" Margin="0,0,90,10" Width="75" 
      Command="{Binding SaveButton_Click}" 
      Background="{Binding IsDirty, Converter={StaticResource IsDirtyConverter}}" Height="20" VerticalAlignment="Bottom"/> 
    <Button Content="Refresh" HorizontalAlignment="Right" Margin="0,0,10,10" Width="75" 
      Command="{Binding RefreshButton_Click}" Height="20" VerticalAlignment="Bottom"/> 

</Grid> 

回答

1

從構造移動你的CodeCollection.CollectionChanged += OnCodeCollectionChanged;代碼爲LoadXml代碼填寫在收集

private void LoadXML() 
    { 
     try 
     { 
      XmlSerializer _serializer = new XmlSerializer(typeof(Codes)); 

      // A file stream is used to read the XML file into the ObservableCollection 
      using (StreamReader _reader = new StreamReader(@"LocalCodes.xml")) 
      { 
       CodeCollection.CollectionChanged -= OnCodeCollectionChanged; 
       CodeCollection = (_serializer.Deserialize(_reader) as Codes).CodeCollection; 
       CodeCollection.CollectionChanged += OnCodeCollectionChanged; 

      }     
     } 

要更改的CodeCollection的實例後,需要重新註冊到事件