WPF:OnCollectionChanged 不触发 [英] WPF: OnCollectionChanged not firing
问题描述
使用 VS 2102、.NET 4.0 和 MVVM Light.
Using VS 2102, .NET 4.0 and MVVM Light.
我有以下代码将 XML 文件中的项目读取到 ObservableCollection 中.如果集合发生变化(使用 IsDirty 标志)但 OnCodeCollectionChanged 方法没有被执行,我想用转换器更新保存按钮.
I have the following code that reads items from an XML file into an ObservableCollection. I then want to update the Save button with a Converter if the collection changes (using an IsDirty flag) but the OnCodeCollectionChanged method is not being executed.
集合正确显示在数据网格中,我可以向数据网格添加新条目,但永远不会调用 OnCodeCollectionChanged 方法.我不想捕捉现有项目的更改(我知道 ObservableCollection 不会通知该更改),我只想在向/从集合中添加或删除新项目时引发 on change 事件.
The collection is properly displayed in the data grid and I can add new entries to the data grid but the OnCodeCollectionChanged method is never called. I am NOT trying to catch the change of an existing item (I know ObservableCollection doesn't notify that change), I just want to raise the on change event if a new item is added or removed to/from the collection.
我做错了什么,有没有更好的方法来做我想做的事?
What am I doing wrong and is there a better way of doing what I want?
Codes.cs(模型)
Codes.cs (Model)
[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 (ViewModel)
MainViewMdoel.cs (ViewModel)
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(视图)
MainWindow.xaml (View)
<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>
推荐答案
移动你的 CodeCollection.CollectionChanged += OnCodeCollectionChanged;
代码从构造函数到 LoadXml
代码合集
Move your CodeCollection.CollectionChanged += OnCodeCollectionChanged;
code from constructor to the LoadXml
code after you fill the collection
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 的实例,需要再次注册该事件
you are changing the instance of the CodeCollection and need to register to the event again
这篇关于WPF:OnCollectionChanged 不触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!