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 は、ItemsSource を介して ListView にバインドされる ObservableCollection です。

<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 インスタンスのプロパティを変更するときに UI を更新するために、クラスINotifyPropertyChangedに実装する必要があります。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 に答える