WPF:OnCollection已更改,未触发

本文关键字:OnCollection WPF | 更新日期: 2023-09-27 18:36:01

Using VS 2102, .NET 4.0 and MVVM Light.

我有以下代码将项目从 XML 文件读取到可观察集合中。 然后,如果集合更改(使用 IsDirty 标志),但未执行 OnCodeCollectionChanged 方法,我想使用转换器更新"保存"按钮。

集合正确显示在数据网格中,我可以向数据网格添加新条目,但永远不会调用 OnCodeCollectionChanged 方法。 我不是在尝试捕获现有项目的更改(我知道 ObservableCollection 不会通知该更改),我只想在向集合中添加或删除新项目时引发更改事件。

我做错了什么,有没有更好的方法来做我想做的事?

代码.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 (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 (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>

WPF:OnCollection已更改,未触发

填充集合后,将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;
            }                
        }

您正在更改代码集合的实例,需要再次注册到事件