0

アイテムの ListBox を含む画面があります。項目テンプレートには、一部のデータがヘッダーに含まれ、一部のデータが展開子のコンテンツ部分に含まれる展開コントロールが含まれています。

ListBox ItemTemplate のデータ テンプレートは次のようになります。

<DataTemplate x:Key="MyTypeTemplate" DataType="{x:Type MyType}">
  <Expander DataContext="{Binding}">
    <Expander.Header>
      <Canvas>
        <TextBox Text="{Binding MyProperty}"/>
      </Canvas>
    </Expander.Header>
    <Canvas>
      <TextBox Text={Binding MyDetailedProperty}"/>
    </Canvas>
  </Expander>
</DataTemplate>

これらのプロパティが変更されるたびに、'MyProperty' または 'MyDetailedProperty' のいずれかが変更されると、エキスパンダー コントロールが折りたたまれていました。これは、データが変更されたときに Expander アイテムが再作成されることに関係していると思います。

追加のデータ項目として、リスト ボックスにバインドされるリストは、.NET 2.0 用に作成されたライブラリから取得されるため、IBindingList を実装します。時間の制約により、ObservableCollection を使用してリストを再作成できません

4

1 に答える 1

0

モデル オブジェクトをビュー オブジェクトにラップして、IsExpandable プロパティを追加し、それを Expanded IsExpanded プロパティにバインドしてデータを公開しました。

これは汎用ソリューションではありませんが、当面の問題は解決します。PropertyChanged および ListChanged イベントのアタッチによって UI オブジェクトでメモリ リークの問題が発生するかどうかは調べていませんが、私の状況では、各オブジェクトは 1 回だけ作成する必要があります。

また、コレクションの変更で Add と Remove 以外のイベントはサポートされていませんが、私の場合は他に何も発生させていないので、無視しても問題ありません。

public class ExpandableItem<T> : INotifyPropertyChanged 
    where T: INotifyPropertyChanged
{
    private bool m_isExpanded;
    private readonly T m_data;

    public ExpandableItem(T data)
    {
        m_data = data;

        m_data.PropertyChanged += 
          delegate 
          { 
            PropertyChanged(this, new PropertyChangedEventArgs("Data")); 
          };
    }

    public bool IsExpanded
    {
        get { return m_isExpanded; }
        set
        {
            if (value != m_isExpanded)
            {
                m_isExpanded = value;
                PropertyChanged(this, new PropertyChangedEventArgs("IsExpanded"));
            }
        }
    }

    public T Data
    {
        get
        {
            return m_data;
        }

    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
} 

public class ExpandableList<TObject,TList> :
  ObservableCollection<ExpandableItem<TObject>>
  where TList : ObservableCollection<TObject>
  where TObject : INotifyPropertyChanged
{
    readonly TList m_list;

    public ExpandableList(TList list) 
        : base(list.Select(obj=>new ExpandableItem<TObject>(obj)))
    {
        list.CollectionChanged += OnListChanged;
        m_list = list;
    }

    public TList Data { get { return m_list; } }

    private void OnListChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            Insert(e.NewStartingIndex, e.NewItems[0]);
        }
        if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            RemoveAt(e.OldStartingIndex);
        }
    }
}
于 2008-12-19T16:39:20.397 に答える