1

パラメータとしてを受け入れるコンバータがありObservableCollection、コレクション内のアイテムの特定のプロパティが変更されるたびに再評価したいと思います。

例:コンバーターを使用してラベルをPersonオブジェクトのコレクションにバインドしたとします。コンバーターの仕事は、リスト内の女性の人の数を数え、女性1人の場合は「有効」、2人の場合は「承認済み」を返すことです。オブジェクトのGenderプロパティがあればいつでもコンバーターを再度呼び出す必要があります。Person変更されます。

どうすればこれを達成できますか?

4

2 に答える 2

3

これは、WPFを十分に長くプレイすると、最終的に発生する典型的な問題です。

私はさまざまな解決策を試しましたが、最も効果的なのは次のようなBindingListを使用することです。

public class WorldViewModel : INotifyPropertyChanged
{
   private BindingList<Person> m_People;
   public BindingList<Person> People
   {
      get { return m_People; }
      set
      {
         if(value != m_People)
         {
            m_People = value;
            if(m_People != null)
            {
               m_People.ListChanged += delegate(object sender, ListChangedEventArgs args)
               {
                  OnPeopleListChanged(this);
               };
            }
            RaisePropertyChanged("People");
         }
      }
   }

   private static void OnPeopleListChanged(WorldViewModel vm)
   {
      vm.RaisePropertyChanged("People");
   }

   public event PropertyChangedEventHandler PropertyChanged;
   void RaisePropertyChanged(String prop)
   {
      PropertyChangedEventHandler handler = this.PropertyChanged;
      if (handler != null)
      {
          handler(this, new PropertyChangedEventArgs(prop));
      }
   }
}

次に、ObservableCollectionで行うのと同じように、Peopleコレクションにバインドします。ただし、アイテム内のプロパティが変更されたときにバインドが再評価されます。

また、OnPeopleListChangedは静的であるため、メモリリークが発生しないことに注意してください。

そして、PersonはINotifyPropertyChangedを実装する必要があります。

于 2012-09-27T13:38:40.207 に答える
0

CollectionChangedイベントは、アイテムがコレクションに追加またはコレクションから削除された場合にのみスローされます(コレクション内のアイテムが変更された場合はスローされません)。したがって、アイテムが変更されたときにコンバーターは呼び出されません。

1つのオプション:
Gender Property Setに、コレクションを評価し、ラベルをバインドする文字列Propertyを設定するロジックを含めます。

ヒヒからの答えのジェネリック版を書いた

public class ObservalbeList<T>: INotifyPropertyChanged
{
    private BindingList<T> ts = new BindingList<T>();

    public event PropertyChangedEventHandler PropertyChanged;

    // This method is called by the Set accessor of each property. 
    // The CallerMemberName attribute that is applied to the optional propertyName 
    // parameter causes the property name of the caller to be substituted as an argument. 
    private void NotifyPropertyChanged( String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public BindingList<T> Ts
    {
        get { return ts; }
        set
        {
            if (value != ts)
            {
                Ts = value;
                if (Ts != null)
                {
                    ts.ListChanged += delegate(object sender, ListChangedEventArgs args)
                    {
                        OnListChanged(this);
                    };
                }
                NotifyPropertyChanged("Ts");
            }
        }
    }

    private static void OnListChanged(ObservalbeList<T> vm)
    {
        vm.NotifyPropertyChanged("Ts");
    }

    public ObservalbeList()
    {
        ts.ListChanged += delegate(object sender, ListChangedEventArgs args)
        {
            OnListChanged(this);
        };
    }
}
于 2012-09-27T12:16:35.830 に答える