3

我有 WPF ListView 的绑定问题。视图模型实现 INotifyPropertyChanged 以在数据更新时触发。但它包含一个未实现 INotifyPropertyChanged 的​​类型(“Person”)的可观察集合。

ListView 会在启动后显示我绑定的人员,这很好。但是在更改了模型的数据(人的年龄)之后,我不知何故需要手动更新视觉表示/绑定 - 这是我的问题。

如果有人能把我踢向正确的方向,我将不胜感激,谢谢!

该模型非常简单:

// does not implement INotifyPropertyChanged interface
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

PersonList 是一个 ObservableCollection,它通过 ItemsSource 绑定到 ListView:

<ListView x:Name="ListViewPersons" ItemsSource="{Binding PersonList}">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"></GridViewColumn>
                <GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}"></GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>

视图的代码隐藏将“年龄增长”委托给视图模型。在模型数据发生这种变化之后,我需要以某种方式更新 GUI,这是我的问题:

private void Button_Click(object sender, RoutedEventArgs e)
    {
           ...

            // increasing the age of each person in the model 
            viewModel.LetThemGetOlder();

            **// how to update the View?**

            // does not work
            ListViewPersons.GetBindingExpression(ListView.ItemsSourceProperty)
                                 .UpdateTarget();

            // does not work either
            ListViewPersons.InvalidateProperty(ListView.ItemsSourceProperty);
        }
    }

为了完成,ViewModel:

class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        PersonList = new ObservableCollection<Person>
            {
                new Person {Name = "Ellison", Age = 56},
                new Person {Name = "Simpson", Age = 44},
                new Person {Name = "Gates", Age = 12},
            };
    }

    internal void LetThemGetOlder()
    {
        foreach (var p in PersonList)
        {
            p.Age += 35;
        }
    }

    private ObservableCollection<Person> _personList;
    public ObservableCollection<Person> PersonList
    {
        get { return _personList; }
        set
        {
            _personList = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
4

2 回答 2

3

当您更改存储在 ObservableCollection 中的 Person 实例的属性时,您还需要INotifyPropertyChanged在您的类上实现以更新 UI。Person

public class Person : INotifyPropertyChanged
{
  private string _name;
  private string _age;

  public string Name { 
    get { 
      return _name;
    }
    set{
      _name = value, 
      OnPropertyChanged();
    }
  }
  public int Age { 
    get { 
     return _age;
    } 
    set{
      _age= value,
    OnPropertyChanged(); 
    }
  }

  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
  }

}

于 2013-06-17T08:30:36.043 回答
3

您可以尝试Items.Refresh();,但我会重新考虑我的课程设计,尤其是您的视图模型和模型。为什么你的模型不实现 INotifyPropertyChanged?为什么不以 1:1 的方式将模型包装在视图模型中?目前您正在使用 WPF,并且只有在有充分理由的情况下才应该这样做。

于 2013-06-17T08:31:25.767 回答