WPF:OnCollectionChanged 不触发 [英] WPF: OnCollectionChanged not firing

查看:78
本文介绍了WPF:OnCollectionChanged 不触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆