8

コレクションのプロパティが変更されたときにObservableCollectionを含むリストボックスを更新する際に問題が発生しました(リストからのアイテムの追加/削除は正常に機能します):

リストボックスが設定さItemsSource="{Binding Path=AllPerson}"れ、コードビハインドのデータコンテキストが次のように設定されていますthis.DataContext = allPersonClass;

allPersonClass含むObservableCollection<Person> allPerson

クラスPersonには、Nameなどのプロパティが含まれています。

ToString個人のメソッドを上書きしてNameプロパティを返すようにしたので、listBoxに有効なデータが表示されます

Person実装してみましたINotifyPropertyChanged

public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(object sender, string propertyName) {
    if (this.PropertyChanged != null) {
        PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
    }
}

public string Name {
     get { return name; }
     set {
        name = value;
        onPropertyChanged(this, "allPersonClass");
     }
}

そして、すべてのプロパティセッターonPropertyChanged(this, "propertyName");で実行されますが、listBoxはすでに作成されたアイテムを更新しません

何が間違っているのでしょうか?

これがlistBoxxamlのウィンドウです

     <Button x:Name="btnDetail" Content="Detail" HorizontalAlignment="Left" Margin="361,249,0,0" VerticalAlignment="Top" Width="75" Click="ButtonDetailClick"/>
     <ListBox x:Name="listPerson" ItemsSource="{Binding Path=AllPerson}" HorizontalAlignment="Left" Height="170" Margin="33,29,0,0" VerticalAlignment="Top" Width="155" IsSynchronizedWithCurrentItem="True"/>
     <Button x:Name="btnLoad" Content="Load" HorizontalAlignment="Left" Margin="58,249,0,0" VerticalAlignment="Top" Width="75" Click="btnLoad_Click"/>
     <Button x:Name="btnSave" Content="Save" HorizontalAlignment="Left" Margin="138,249,0,0" VerticalAlignment="Top" Width="75" Click="ButtonSaveClick"/>

これは、変更が行われる(Personにバインドされる)DetailViewウィンドウの一部です。

<TextBox Text="{Binding Path=Name}" Height="23" HorizontalAlignment="Left" Margin="118,20,0,0" Name="txtName" VerticalAlignment="Top" Width="141" />

これがAllPersonClassの一部です:

public class AllPersonClass {
  private ObservableCollection<Person> allPerson;

public AllPersonClass() {
     allPerson = new ObservableCollection<Person>();
  }

public ObservableCollection<Person> AllPerson {
     get { return allPerson; }
     set { allPerson = value; }
  }

 public void addPerson(Person newPerson) {
     allPerson.Add(newPerson);
  }


public Person getPerson(int personIndex) {
     return allPerson[personIndex];
  }
}

編集

詳細ビューで変更を保存する方法の関連部分は次のとおりです

private void OnBtnSaveClick(object sender, RoutedEventArgs e) {
     person.Name = txtName.Text;
     person.SurName = txtSurName.Text;
}

「ObservableCollectionallPerson」で変更が行われることに注意してください。listBoxのみが古いデータを表示し続けます

4

4 に答える 4

11

Personプロパティに変更を加えたときにUIを更新する場合は、クラスではなく、そのプロパティが変更されたことを通知する必要があります。

public string Name 
{
     get { return name; }
     set 
     {
        name = value;
        onPropertyChanged(this, "allPersonClass");
     }
}

<TextBox Text="{Binding Path=Name}" .....

する必要があります

public string Name 
{
     get { return name; }
     set 
     {
        name = value;
        onPropertyChanged(this, "Name");
     }
}

<TextBox Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" .....

また、で正しく表示するためにモデルをオーバーライドToString()する必要はありません。で必要なプロパティを表示するようにを設定できます。PersonListBoxListBox DisplayMemberPathListBox

  <ListBox ItemsSource="{Binding Path=AllPerson}" DisplayMemberPath="Name" />

編集:コメントの質問に答える:

public string Name 
{
     get { return name; }
     set 
     {
        name = value;
        onPropertyChanged(this, "Name");
        onPropertyChanged(this, "Display");
     }
}

public string Surname
{
     get { return surname; }
     set 
     {
        surname= value;
        onPropertyChanged(this, "Surname");
        onPropertyChanged(this, "Display");
     }
}

public string Display
{
     get { return Name + " " + Surname; }
}
于 2013-03-13T22:07:00.323 に答える
5

DetailViewで、personクラスのプロパティ名を更新するためにTwoWay-Bindingを定義する必要があります。

<TextBox Text="{Binding Path=Name, Mode=TwoWay}" Height="23" HorizontalAlignment="Left" Margin="118,20,0,0" Name="txtName" VerticalAlignment="Top" Width="141" />

また、テキストが書き込まれるたびにプロパティを更新する場合は、UpdateSourceTriggerwithを定義する必要もありますPropertyChanged。それ以外の場合、プロパティはTextBoxがフォーカスを失ったときにのみ更新されます。

<TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="23" HorizontalAlignment="Left" Margin="118,20,0,0" Name="txtName" VerticalAlignment="Top" Width="141" />
于 2013-03-13T21:55:06.077 に答える
4

あなたの問題はあなたのコレクションがあなたのPropertyChangedについて決して通知されないということです

これはあなたを助けるはずです

ObservableCollection<INotifyPropertyChanged> items = new ObservableCollection<INotifyPropertyChanged>();
    items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(items_CollectionChanged);


    static void items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        foreach (INotifyPropertyChanged item in e.OldItems)
            item.PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);

        foreach (INotifyPropertyChanged item in e.NewItems)
            item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
    }

    static void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        throw new NotImplementedException();
    }

このリンクも参照してください

于 2013-03-14T09:01:41.403 に答える
3

アイテムレベルでバインディングをどのように行っているかを確認することをお勧めします。このリンクをチェックしてください、それはあなたが始めるでしょう:

ObservableCollection<T>の行が実際に変更されたかどうかを判断する方法

于 2013-03-13T21:40:31.880 に答える