0

我在 WPF 中有一个使用 MVVM 模式的项目。

该视图有一个 Persons(FirstName, LastName, Town) 的列表视图,列表旁边是人员的详细信息 (FirstName,LastName,ZIP),带有一个按钮 (Save)。如果您点击左侧的某个人,右侧的人员详细信息将自动加载。

在 ViewModel 中,我有一个 ObservableCollection 的 Person-Models。(人员名单)

Person 模型包括一些属性,例如 FirstName、LastName、Town、Zip。(细节)。

当我更改 ZIP 时,Town 将自动更新(在设置器开关情况下),例如 ZIP '11111' Town 'Town1' / ZIP '22222' Town 'Town2'。

Person 模型还包括一个用于保存更改的 ICommand“SavePerson”。

现在,当我单击列表视图中的某个项目时,详细信息将自动加载。当我更改名字或姓氏并单击“保存”时,列表视图将更改所选项目的名字和姓氏,没关系。现在,当我将 ZIP 从“12345”更改为“11111”时,列表视图中的城镇仍然是旧的,而不是“Town1”。

您是否有解决此问题的想法,而无需在模型中实现 INotifyPropertyChanged-Interface?

一些代码: 型号:

public class Person
{
    private string _firstName = string.Empty;
    private string _lastName = string.Empty;
    private string _zip = string.Empty;
    private string _town = string.Empty;

    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; }
    }

    public string LastName
    {
        get { return _lastName; }
        set { _lastName= value; }
    }

    public string ZIP
    {
        get { return _zip; }
        set
        {
            switch (value)
            {
                case "11111":
                    this.Town = "Town1";
                    break;
                case "22222":
                    this.Ort = "Town2";
                    break;
                default:
                    break;
            }
            _zip = value;
        }
    }

    public string Town
    {
        get { return _town; }
        set { _town= value; }
    }
            public ICommand SaveNameCommand
    {
        get
        {
            return new DelegateCommand((param) => this.SaveName(param));
        }
    }

    private void SaveName(object parameter)
    {
        string[] param = ((string)parameter).Split(new char[] { ':' });
        FirstName = param[0];
        LastName = param[1];
        PLZ = param[2];
    }
}

视图模型:

public class PersonList
{
    private readonly ObservableCollection<Person> _persons = new ObservableCollection<Person>();
    private Person _currentSelectedPerson = new Person();

    public PersonList()
    {
        this._persons.Add(new Person() { FirstName = "First1", LastName = "Last1", Ort = "Ort1", PLZ = "112" });
        this._persons.Add(new Person() { FirstName = "First2", LastName = "Last2", Ort = "Ort2", PLZ = "122" });
        this._persons.Add(new Person() { FirstName = "First3", LastName = "Last3", Ort = "Ort3", PLZ = "1132" });
    }

    public IEnumerable<Person> Persons
    {
        get { return this._persons; }
    }
}
4

4 回答 4

2

由于您的模型应该与您的视图模型松散耦合,因此您可能不想在模型中实现 INotifyPropertyChanged 是有道理的,因为它最常与 WPF 相关联;但是,它是一个 C# 接口,可以在任何类型的应用程序中使用,因此实现它并没有什么坏处。事实上,我认为这可能是最好的方法。但是,如果您真的不想在模型类中实现它,请考虑一个事件订阅模型,其中模型在更改时引发事件,而 ViewModel 订阅它。

model.ValuesChanged += model_ValuesChanged;

private void model_ValuesChanged(object sender, EventArgs e)
{
     RaisePropertyChanged("MyProperty");
}
于 2013-10-31T09:32:05.617 回答
1

我完全不知道为什么你不想你的模型类上实现INotifyPropertyChanged接口。实际上,您唯一的其他选择是在您的视图模型中实现它并在那里公开您的所有模型属性:

public string FirstName
{
    get { return _currentSelectedPerson .FirstName; }
    set { _currentSelectedPerson .FirstName = value; NotifyPropertyChanged("FirstName"); }
}

public string LastName
{
    get { return _currentSelectedPerson .LastName; }
    set { _currentSelectedPerson .LastName= value; NotifyPropertyChanged("LastName"); }
}
...

WPF 和INotifyPropertyChanged接口齐头并进……在某个阶段,您将不得不实现它。

于 2013-10-31T09:22:04.080 回答
0

模型应该实现 INotifyPropertyChanged chack INotifyPropertyChanged WPF
任何其他搜索 INotifyPropertyChanged 也可以

于 2013-10-31T09:03:58.187 回答
0

您需要通知您的 View 关于 ViewModel 中的更改。为此使用INotifyPropertyChanged。任何实现此接口的类都会在属性发生更改时通知任何侦听器。

所以你需要再修改一下我们的 Person 类:

public class Person : INotifyPropertyChanged
{
    private string _firstName = string.Empty;
    private string _lastName = string.Empty;
    private string _zip = string.Empty;
    private string _town = string.Empty;

    public string FirstName
    {
        get { return _firstName; }
        set 
        {
            _firstName = value; 
            RaisePropertyChanged("FirstName");
        }
    }

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

    public string ZIP
    {
        get { return _zip; }
        set
        {
            switch (value)
            {
                case "11111":
                    this.Town = "Town1";
                    break;
                case "22222":
                    this.Town = "Town2";
                    break;
                default:
                    break;
            }
            _zip = value;
            RaisePropertyChanged("LastName");
            RaisePropertyChanged("Town");
        }
    }

    public string Town
    {
        get { return _town; }
        set 
        {
            _town= value; 
            RaisePropertyChanged("Town");
        }
    }
            public ICommand SaveNameCommand
    {
        get
        {
            return new DelegateCommand((param) => this.SaveName(param));
        }
    }

    private void SaveName(object parameter)
    {
        string[] param = ((string)parameter).Split(new char[] { ':' });
        FirstName = param[0];
        LastName = param[1];
        PLZ = param[2];
    }
}
于 2013-10-31T10:37:59.470 回答