代码之家  ›  专栏  ›  技术社区  ›  Tatranskymedved

C#-如何处理模型的属性更改以在ViewModel中调用notify

  •  0
  • Tatranskymedved  · 技术社区  · 7 年前

    遵循MVVM体系结构,我们可以看到2 DataGrids 其数据相关且视图模型具有 ObservableCollection<Model>

    模型具有布尔属性,基于该属性启用/禁用网格之一。当我更改选定的 Model ,网格变得不可用。但是,当我更改属性时 Notify 客户财产的 IsSelectedModelChecked 未调用(当我选中/取消选中第一个网格中的复选框时,我需要调用 通知 在物业上方 IsSelectedModelChecked已选中 )。

    Q: 如何在模型的属性更改时调用属性更改?

    我检查了几个问题,但没有一个回答我的问题。我很想从头开始提供一些想法,但我没有任何线索。谢谢


    <输入不必要的代码(>);

    XAML:

    <DataGrid
          ItemsSource="{Binding Models}"
          SelectedItem="{Binding SelectedModel}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name"
                     Binding="{Binding Name}"/>
            <DataGridCheckBoxColumn Header="Check"
                     Binding="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}">
        </DataGrid.Columns>
    </DataGrid>
    
    <DataGrid
          IsEnabled="{Binding IsSelectedModelChecked}"/>
    

    型号:

    public class Model : Microsoft.VisualStudio.PlatformUI.ObservableObject
    {
        private string mName = @"<Name>";
        public string Name
        {
            get { return mName; }
            set { SetProperty(ref mName, value); }
        }
    
        private bool mIsChecked = false;
        public bool IsChecked
        {
            get { return mIsChecked; }
            set { SetProperty(ref mIsChecked, value); }
        }
    }
    

    视图模型:

    public class ViewModel : Microsoft.VisualStudio.PlatformUI.ObservableObject
    {
        private Model mSelectedModel;
        public Model SelectedModel
        {
            get { return mSelectedModel; }
            set
            {
                SetProperty(ref mSelectedModel, value);
                NotifyPropertyChanged(nameof(IsSelectedModelChecked));
            }
        }
    
        private ObservableCollection<Model> mModels = new ObservableCollection<Model>();
        public ObservableCollection<Model> Models
        {
            get { return mModels; }
            set { SetProperty(ref mModels, value); }
        }
    
        public bool IsSelectedModelChecked => SelectedModel?.IsChecked ?? false;
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Haukinger    7 年前

    你必须倾听 SelectedModel PropertyChanged 事件

    一、 e。

    public Model SelectedModel
    {
        get { return mSelectedModel; }
        set
        {
            if (mSelectedModel != null)
                mSelectedModel.PropertyChanged -= OnSelectedModelPropertyChanged;
            SetProperty(ref mSelectedModel, value);
            if (mSelectedModel != null)
                mSelectedModel.PropertyChanged += OnSelectedModelPropertyChanged;
            NotifyPropertyChanged(nameof(IsSelectedModelChecked));
        }
    }
    
    private void OnSelectedModelPropertyChanged( object sender, PropertyChangedEventArgs args )
    {
        if (args.PropertyName == nameof(Model.IsChecked))
            NotifyPropertyChanged(nameof(IsSelectedModelChecked));
    }
    

    此外,如果模型实例的寿命比视图模型长,您还需要小心泄漏视图模型实例。

        2
  •  0
  •   Tatranskymedved    7 年前

    这是对 Haukinger 的答案。他提到了内存泄漏问题,当ViewModel实例将被销毁时,可能会发生内存泄漏,但模型将存在,并且处理程序仍将附加到事件。

    在这种情况下,WPF实现了一种称为 Weak Event Pattern ,允许处理此类情况。对于属性更改,存在 PropertyChangedEventManager 实现如此弱的事件模式。代码应编写为:

    public Model SelectedModel
    {
        get { return mSelectedModel; }
        set
        {
            if (mSelectedModel != null)
                PropertyChangedEventManager.RemoveHandler(mSelectedModel, OnSelectedModelPropertyChanged, "");
    
            SetProperty(ref mSelectedModel, value);
    
            if (mSelectedModel != null)
                PropertyChangedEventManager.AddHandler(mSelectedModel, OnSelectedModelPropertyChanged, "");
    
            NotifyPropertyChanged(nameof(IsSelectedModelChecked));
        }
    }
    
    private void OnSelectedModelPropertyChanged( object sender, PropertyChangedEventArgs args)
    {
        if (args.PropertyName == nameof(Model.IsChecked))
            NotifyPropertyChanged(nameof(IsSelectedModelChecked));
    }