MVVM刷新模型

时间:2013-10-31 08:29:17

标签: wpf mvvm observablecollection inotifypropertychanged icommand

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

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

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

人物模型包括一些属性,如FirstName,LastName,Town,Zip。 (详细说明)。

当我更改ZIP时,Town会自动更新(在setter switch-case中),例如ZIP'11111'Town'Town1'/ ZIP'22222'Town'Town2'。

Person Model还包含一个ICommand“SavePerson”来保存更改。

现在,当我点击列表视图中的某个项目时,详细信息将自动加载。 当我更改FirstName或LastName并单击“保存”时,列表视图将更改所选项目的First和LastName,这没关系。 现在,当我将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 个答案:

答案 0 :(得分:2)

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

model.ValuesChanged += model_ValuesChanged;

private void model_ValuesChanged(object sender, EventArgs e)
{
     RaisePropertyChanged("MyProperty");
}

答案 1 :(得分: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界面齐头并进...在某个阶段,您将不得不实施它。

答案 2 :(得分:0)

模型应该实现INotifyPropertyChanged chack INotifyPropertyChanged WPF
对INotifyPropertyChanged的任何其他搜索也会这样做

答案 3 :(得分:0)

您需要在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];
    }
}