与基类的PropertyChange MVVM INotifyPropertyChanged的冲突 [英] MVVM INotifyPropertyChanged conflict with base class PropertyChange

查看:85
本文介绍了与基类的PropertyChange MVVM INotifyPropertyChanged的冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是比较新的MVVM,我想了解如何INotifyPropertyChanged接口工作以及如何实现它在我的模型。我决定采取的方法是实现它在每一个我的业务对象类的。结果这种做法的问题是,当我在我查看该基类中的PropertyChanged事件绑定到属性的基类永远不会被初始化(为空),因此查看时不刷新数据,该元素我模型更改。我可以用以下的例子来重现问题。

I'm relatively new to MVVM and I'm trying to understand how INotifyPropertyChanged interface works and how to implement it in my models. The approach that I decided to take was to implement it in each of my Business Object classes.
The problem with that approach is that when I bind my View to a property in a Base class the PropertyChanged event in that base class never gets initialized (is null) and therefore the View does not refresh the data for that element when my Model changes. I was able to reproduce the problem with the example below.

我有一个Person基类:

I have a Person Base class:

 public class Person : INotifyPropertyChanged
    {
        #region INotifyProperty

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

        public String Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                RaisePropertyChanged("Name");
            }
        }
        private String _name;
    }

和我有一个Employee类从我个人的基类继承:

And I have an Employee class inheriting from my Person Base class:

 public class Employee : Person,INotifyPropertyChanged
    {
        #region INotifyProperty

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion


        public String EmployeeID
        {
            get
            {
                return _employeeId;
            }
            set
            {
                _employeeId = value;
                RaisePropertyChanged("EmployeeID");
            }
        }
        private String _employeeId;
    }

下面我视图模型:

 public class ViewModel : ViewModelBase<ViewModel>
    {
        private Employee _employee;

        public ViewModel()
        {
            ChangeModelCommand = new RelayCommand(param=>this.ChangeModel() , param=>this.CanChangeModel);
            Employee = new Employee()
                         {
                             Name = "BOB",EmployeeID = "1234"
                         };
        }

        public ICommand ChangeModelCommand { get; set; }


        public Employee Employee
        {
            get
            {
                return _employee;
            }
            set
            {
                this._employee = value;
                NotifyPropertyChanged(m=>m.Employee);
            }
        }

        public void ChangeModel()
        {
            MessageBox.Show("CHANGING MODEL");
            this.Employee.Name = "MIKE";
            this.Employee.EmployeeID = "5678";
        }
        public bool CanChangeModel
        {
            get{ return true;}
        }
    }

最后我的观点:

<Window.Resources>
    <MVVM_NotificationTest:ViewModel x:Key="Model"></MVVM_NotificationTest:ViewModel>
</Window.Resources>
<Grid DataContext="{StaticResource Model}">
<StackPanel>
    <Label Content="Employee Name"/>
    <TextBox Text="{Binding     Path=Employee.Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    <Label Content="Employee ID"/>
    <TextBox Text="{Binding Path=Employee.EmployeeID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    <Button Content="Change Model" Height="30" Width="100" Margin="5" Command="{Binding Path=ChangeModelCommand}"/>
</StackPanel>
</Grid>

在这个例子中我初始化我的员工VM物业在VM构造函数,然后我有一个命令来修改雇员(从Employee类)和名称(从Person类)。然而,在认为被更新的唯一UI元素是雇员,而不是名称(我的预期鲍勃更新到迈克)。搜索结果在调试我发现PropertyChanged事件是我的基类总是空(人)。我还注意到,当我从我的Employee类的一切删除整个#INotifyProperty区域,因为它使用的是基本类型的事件和方法的正常工作。搜索结果我有这样做的问题是,所有我目前的模型类实现明确INotifyPropertyChanged的。他们都定义了一个PropertyChanged事件并实现RaisePropertyChanged方法,这显然会在我的MVVM的应用程序影响我的绑定。搜索结果最后,我想澄清的是,我不希望在我的ViewModel缠上了我的模型属性,并依靠虚拟机INPC机制。我想已经用我的模型INPC执行到位有内部消除有条件地去除取决于我是否从一个基类继承或不INPC实现。
搜索结果
综上所述,我想知道什么是实现INPC我深深的分层模型,因此继承不破的PropertyEvent传播,因为我们在这个例子中看到的所以我的独立的类可以自给自足,以及最好的方式。任何意见或建议,将大大AP preciated:)

In this example I initialize my Employee VM Property in the VM constructor and then I have a command to modify the EmployeeID (from Employee class) and Name (from Person Class). However, the only UI element in the View that gets updated is the EmployeeID and not the Name (I expected Bob to update to Mike).

While debugging I found that PropertyChanged event was always null in my base class (Person). I also noticed that when I remove the whole #INotifyProperty region from my Employee class everything works fine since it is using the Base Type event and methods.

The problem I have with that is that all my current model classes implement INotifyPropertyChanged explicitly. They all define a PropertyChanged event and implement the RaisePropertyChanged method, which obviously will impact my bindings in my MVVM application.

Lastly, I want to clarify that I do not want wrap my Model properties in my ViewModel and rely on the VM INPC mechanism. I would like to use my Model INPC implementation already in place whithout having to conditionally remove the INPC implementations depending on whether I am inheriting or not from a base type.

In summary, I would like to know what's the best way to implement the INPC in my deeply hierarchical model so that inheritance doesn't break the PropertyEvent propagation as we saw in this example and so my independent classes can be self sufficient as well. Any ideas or suggestions will be greatly appreciated :)

推荐答案

只要让RaisePropertyChanged保护,并将其移动到基类。目前,你会有很多的重复是没有必要的。

Simply make RaisePropertyChanged protected and move it into the base class. Currently you will have a lot of duplication that is not necessary.

事情是这样的:

protected virtual void RaisePropertyChanged(string propertyName);

许多MVVM框架为你提供了这一点。例如PRISM有一个<一个href=\"http://msdn.microsoft.com/en-us/library/microsoft.practices.prism.viewmodel.notificationobject%28v=pandp.40%29.aspx\">NotificationObject视图模型基类。

这篇关于与基类的PropertyChange MVVM INotifyPropertyChanged的冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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