Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf OnPropertyChanged的替代方案_Wpf_Mvvm_Inotifypropertychanged - Fatal编程技术网

Wpf OnPropertyChanged的替代方案

Wpf OnPropertyChanged的替代方案,wpf,mvvm,inotifypropertychanged,Wpf,Mvvm,Inotifypropertychanged,我试图解决在WPF中实现MVVM时遇到的一个问题。下面我的Contact类是由实体框架填充的我的模型 public class Contact : INotifyPropertyChanged { public string _firstName; public string FirstName { get { return _firstName; } set {

我试图解决在WPF中实现MVVM时遇到的一个问题。下面我的
Contact
类是由实体框架填充的我的模型

public class Contact : INotifyPropertyChanged
{
    public string _firstName;
    public string FirstName
    {
        get
        {
            return _firstName;
        }
        set
        {
            _firstName = value;
            OnPropertyChanged("FirstName");
        }
    }

    public string _lastName;
    public string LastName
    {
        get
        {
            return _lastName;
        }
        set
        {
            _lastName = value;
            OnPropertyChanged("LastName");
        }
    }

    //INotifyPropertyChanged implementation omitted for brevity
}
以下是我的ViewModel:

public class ContactViewModel
{
    public Contact MyContact { get; set; }

    public string FullName
    {
        get
        {
            return MyContact.FirstName + " " + MyContact.LastName;
        }
    }
}
因此,我将视图的数据源设置为
ContactViewModel
的一个实例,并将两个文本框绑定到
MyContact.FirstName
MyContact.LastName
。我正在将
文本块
绑定到
全名
。当我更改任一文本框时,全名
TextBlock
不会更新(显然,我没有在任何地方执行
OnPropertyChanged(“全名”)

问题是,我在哪里添加
OnPropertyChanged(“全名”)
我不一定要修改我的模型,因为它正在其他地方使用,我不想将它绑定到我的ViewModel。

我需要重新思考我的架构吗

我需要重新思考我的架构吗

这可以通过您当前的体系结构来解决。您只需要将调用从
联系人
对象传播到viewModel对象

您需要在viewModel中实现
INotifyPropertyChanged
,才能实现这一点

大概是这样的:

我还建议大家看一看,因为这包括一个名为
PropertyObserver
的类,它的设计目的是使这类事情的连接更加容易

如果您想采用Big Daddy建议的更纯粹的MVVM方法,您需要执行以下操作:

我需要重新思考我的架构吗

这可以通过您当前的体系结构来解决。您只需要将调用从
联系人
对象传播到viewModel对象

您需要在viewModel中实现
INotifyPropertyChanged
,才能实现这一点

大概是这样的:

我还建议大家看一看,因为这包括一个名为
PropertyObserver
的类,它的设计目的是使这类事情的连接更加容易

如果您想采用Big Daddy建议的更纯粹的MVVM方法,您需要执行以下操作:

也许

在我看来,您正在将视图的属性绑定到视图模型(ContactViewModel)和模型(Contact)。您的视图可以通过视图模型查看公共模型的属性等-我认为这不好。这似乎违反了德米特法。我宁愿看到您使用视图模型作为模型的包装器/外观。这无疑会带来更多的工作,但我认为这会给您带来更好的设计和更大的灵活性。视图模型需要实现
INotifyPropertyChanged
,才能工作

也许



在我看来,您正在将视图的属性绑定到视图模型(ContactViewModel)和模型(Contact)。您的视图可以通过视图模型查看公共模型的属性等-我认为这不好。这似乎违反了德米特法。我宁愿看到您使用视图模型作为模型的包装器/外观。这无疑会带来更多的工作,但我认为这会给您带来更好的设计和更大的灵活性。您的视图模型需要实现
INotifyPropertyChanged
,才能正常工作。

问题是:我不一定要修改我的模型,因为它正在其他地方使用,我不需要将它绑定到我的视图模型。因此,当任何属性发生更改时,这将触发OnPropertyChanged(“全名”),而不仅仅是FirstName或LastName,正确吗?@MikeCole是的,但如果您想避免,只需在属性更改处理程序中添加一个
if(e.PropertyName==“FirstName”| | e.PropertyName==“LastName”)
检查即可。(另外,在尝试连接和分离setter中的
属性已更改的处理程序之前,您需要检查myContact
是否为
null
)@Mike Cole-Rachel说的话^@Rachel我想这是您今天第二次帮助我,谢谢!问题是:我不一定要修改我的模型,因为它正在其他地方使用,我不想将它绑定到我的ViewModel。因此,当任何属性发生更改时,这将触发OnPropertyChanged(“全名”),而不仅仅是FirstName或LastName,对吗?@MikeCole是的,但如果您想避免,只需添加一个
if(e.PropertyName==“FirstName”| e.PropertyName==“LastName”)
检查属性更改处理程序。(此外,在尝试附加和分离setter中的
属性更改处理程序之前,您还需要检查
\u myContact
是否为
null
)@Mike Cole-Rachel说的话^@Rachel我想这是你今天第二次帮助我了,谢谢!通常是ViewModel实现了INPC接口,而不是模型。如果是这样的话,我该如何绑定到我的模型?有些人复制了他们ViewModel上的属性。这些属性包装了模型和视图上的属性仅绑定到您的viewModel。这两种方法都是有效的。确切地说,viewModel只包含需要由视图显示或操作的属性。VM中的属性使用模型的属性作为其支持字段。通常是viewModel实现INPC接口,而不是模型。如果是这种情况,如何d我绑定到我的模型?有些人复制他们的viewModel上的属性。这些属性包装模型上的属性,而您的视图仅绑定到您的viewModel。这两种方法都是有效的。确切地说,viewModel只包含需要视图显示或操纵的属性。VM中的属性使用t的属性他将模型作为他们的支持字段。问题是我的模型实现了IDataErrorInfo并进行了验证。现在,这将传递到我的视图中,并被优雅地处理。如果映射到ViewModel的属性,我会丢失这些验证规则吗?P
public class ContactViewModel : INotifyPropertyChanged
{
    //INotifyPropertyChanged implementation omitted for brevity...

    private Contact _myContact;

    public Contact MyContact 
    { 
        get
        {
            return _myContact;
        } 
        set
        {
            _myContact.PropertyChanged -= myHandler;
            _myContact = value;
            _myContact.PropertyChanged += myHandler;
        }
    }

    public string FullName
    {
        get
        {
            return MyContact.FirstName + " " + MyContact.LastName;
        }
    }

    private void myHandler(Object sender, PropertyChangedEventArgs e)
    {
        OnPropertyChanged("FullName");
    }
}
public class ContactViewModel : INotifyPropertyChanged
{
    // INotifyPropertyChanged implementation omitted for brevity...

    // You will require some way of setting this, either via a property
    // or the viewModel constructor...
    private Contact _myContact;

    public string FirstName
    {
        get { return _myContact.FirstName; }
        set
        {
            _myContact.FirstName = value;
            OnPropertyChanged("FirstName");
            OnPropertyChanged("FullName");
        }
    }

    public string LastName
    {
        get { return _myContact.LastName; }
        set
        {
            _myContact.LastName = value;
            OnPropertyChanged("LastName");
            OnPropertyChanged("FullName");
        }
    }

    public string FullName
    {
        get
        {
            return MyContact.FirstName + " " + MyContact.LastName;
        }
    }
}
Do I need to rethink my architecture?