INotifyPropertyChange不会触发

时间:2018-01-15 13:06:43

标签: c# wpf mvvm

编辑:请参阅课程结构。 INotifyPropertyChanged在ComMethodA情况下工作正常,并按预期触发事件。为什么它在ComMethodB情况下不起作用?

编辑2: 请参阅视图模型代码。

在我的应用程序中,我有几个视图和ViewModel。 所有ViewModel都继承自ViewModelBase,它创建了我的模型的单例对象,我们将其称为MainModel,具有以下结构:

public class MainModel : INotifyPropertyChanged
{
   public string Name {get; set; }
   public List<ISystem> SystemsList{get;set;}   
   public IComMethod ComMethodA {get;set;}   // TEST 1
   public MainModel()
   {
       ComMethodA = new ClassC();
      // let's assume that the other props are initialized
   }
}

public class System: ISystem, INotifyPropertyChanged 
{
   public IComMethod ComMethodB {get;set;}   // TEST 2
   public System()
   {
      ComMethodB = new classC(); // classC implements INotifyPropertyChanged, IComMethod
   }
}

public class ClassC() : IComMethod, INotifyPropertyChanged 
{
    public bool isOpen {get;set;}
    public ClassC()
    {
        // ctor..
    }
}

ViewModelA:

    ctor() 
    {
        MainModel.SystemsList[0].ComMethodB.PropertyChanged += ComMethodB_PropertyChanged;
        MainModel.ComMethodA.PropertyChanged += ComMethodA_PropertyChanged;     
    }
    private void ComMethodB_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
          MessageBox.Show("TextB");
    }
    private void ComMethodA_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
      MessageBox.Show("TextA");
    }

ViewModel B:

MainModel.ComMethodA.isOpen = true; // FIRES event in ViewModelA
MainModel.SystemsList[0].ComMethodB.isOpen = true; // DOESN'T fires event in ViewModelA

在ViewModelA中,我实现了TEST 1&amp; amp;测试2属性。 在ViewModelB中,我正在改变&#39; isOpen&#39;属性。

问题是该事件仅在ComMethodA&#39;情景,但我希望它在“ComMethodB&#39;场景。

由于

1 个答案:

答案 0 :(得分:2)

我怀疑问题出在您没有发布的代码中。如果我不得不猜测,我说它与ViewModelBase类中的MainModel单例有关 - 也许ViewModelA / B正在获得MainModel的不同实例?

我填写了问题代码中的空白,它似乎对我有用。 注意:由于名称空间冲突,我将类System重命名为Systems。

using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace WpfApp9
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            // Setup the ViewModels
            var vmA = new ViewModelA();
            var vmB = new ViewModelB();

            // Test ViewModelB
            vmB.DoIt();
        }
    }

    public class MainModel : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected bool SetProperty<T>(ref T field, T value, [CallerMemberName]string name = null)
        {
            if (Equals(field, value))
            {
                return false;
            }
            field = value;
            this.OnPropertyChanged(name);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName]string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        #endregion

        #region Property List<ISystem> SystemsList
        private List<ISystem> _SystemsList;
        public List<ISystem> SystemsList { get { return _SystemsList; } set { SetProperty(ref _SystemsList, value); } }
        #endregion

        #region Property IComMethod ComMethodA
        private IComMethod _ComMethodA;
        public IComMethod ComMethodA { get { return _ComMethodA; } set { SetProperty(ref _ComMethodA, value); } }
        #endregion

        public MainModel()
        {
            SystemsList = new List<ISystem>() { new Systems() };
            ComMethodA = new ClassC();
        }
    }

    public interface ISystem
    {
        IComMethod ComMethodB { get; set; }
    }
    public interface IComMethod : INotifyPropertyChanged
    {
        bool isOpen { get; set; }
    }

    public class Systems : ISystem, INotifyPropertyChanged
    {
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected bool SetProperty<T>(ref T field, T value, [CallerMemberName]string name = null)
        {
            if (Equals(field, value))
            {
                return false;
            }
            field = value;
            this.OnPropertyChanged(name);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName]string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        #endregion

        #region Property IComMethod ComMethodB
        private IComMethod _ComMethodB;
        public IComMethod ComMethodB { get { return _ComMethodB; } set { SetProperty(ref _ComMethodB, value); } }
        #endregion

        public Systems()
        {
            ComMethodB = new ClassC();
        }
    }

    public class ClassC : IComMethod, INotifyPropertyChanged
    {
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected bool SetProperty<T>(ref T field, T value, [CallerMemberName]string name = null)
        {
            if (Equals(field, value))
            {
                return false;
            }
            field = value;
            this.OnPropertyChanged(name);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName]string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        #endregion

        #region Property bool isOpen
        private bool _isOpen;
        public bool isOpen { get { return _isOpen; } set { SetProperty(ref _isOpen, value); } }
        #endregion
    }

    public class ViewModelBase : INotifyPropertyChanged
    {
        public static MainModel MainModel { get; } = new MainModel();

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected bool SetProperty<T>(ref T field, T value, [CallerMemberName]string name = null)
        {
            if (Equals(field, value))
            {
                return false;
            }
            field = value;
            this.OnPropertyChanged(name);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName]string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        #endregion
    }

    public class ViewModelA : ViewModelBase
    {
        public ViewModelA()
        {
            MainModel.SystemsList[0].ComMethodB.PropertyChanged += ComMethodB_PropertyChanged;
            MainModel.ComMethodA.PropertyChanged += ComMethodA_PropertyChanged;
        }

        private void ComMethodB_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            MessageBox.Show("TextB");
        }

        private void ComMethodA_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            MessageBox.Show("TextA");
        }
    }

    public class ViewModelB : ViewModelBase
    {
        public ViewModelB()
        {
        }

        public void DoIt()
        {
            MainModel.ComMethodA.isOpen = true; // this fired off the "TextA" messagebox
            MainModel.SystemsList[0].ComMethodB.isOpen = true; // this fired off the "TextB" messagebox
        }
    }
}