【问题标题】:MVVM refresh modelMVVM 刷新模型
【发布时间】:2013-10-31 08:29:16
【问题描述】:

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

该视图有一个人员列表视图(名字、姓氏、城镇),列表旁边是人员的详细信息(名字、姓氏、ZIP)和一个按钮(保存)。 如果你点击左侧的人,右侧的人的详细信息会自动加载。

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

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

当我更改 ZIP 时,Town 将自动更新(在 setter 开关盒中),例如邮编“11111”镇“镇1”/邮编“22222”镇“镇2”。

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; }
    }
}

【问题讨论】:

  • 您应该添加一些代码来获得答案吗?很难说哪里出了问题
  • 如果你的代码在你面前都找不到问题,那一群陌生人怎么会在没有代码的情况下解决它!

标签: wpf mvvm observablecollection inotifypropertychanged icommand


【解决方案1】:

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

model.ValuesChanged += model_ValuesChanged;

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

【讨论】:

    【解决方案2】:

    我完全不知道你为什么要在你的模型类上实现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 接口齐头并进……在某个阶段,您将不得不实现它。

    【讨论】:

      【解决方案3】:

      模型应该实现 INotifyPropertyChanged 查克INotifyPropertyChanged WPF
      对 INotifyPropertyChanged 的​​任何其他搜索也可以进行

      【讨论】:

      • 在模型中不实现接口的情况下是否有其他机会解决问题?在大多数教程中,INotifyPropertyChanged 接口将在 ViewModel 中实现。当我在模型中实现接口时,保存按钮不再起作用......
      • 替换整个 person 对象 - 将其从集合中删除并放回原处即可,但这不是一个好方法
      【解决方案4】:

      您需要通知您的视图关于 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];
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2010-10-28
        • 1970-01-01
        • 2020-11-11
        • 1970-01-01
        • 2019-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-30
        相关资源
        最近更新 更多