0

我有一个带有项目列表框的屏幕。项目模板包含一个扩展器控件,其中一些数据位于标题中,一些数据位于扩展器的内容部分。

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 项目有关。

作为附加数据项,绑定到列表框的列表实现了 IBindingList,因为它来自为 .NET 2.0 创建的库。由于时间限制,我无法使用 ObservableCollection 重新创建列表

4

1 回答 1

0

我最终将我的模型对象包装在一个视图对象中,该对象添加了一个 IsExpandable 属性,我可以将其绑定到 Expanded IsExpanded 属性,然后公开数据。

这不是通用解决方案,但它解决了我的直接问题。我看到的尚未探索的可能问题是附加的 PropertyChanged 和 ListChanged 事件是否会导致我的 UI 对象出现内存泄漏问题,但在我的情况下,每个对象应该只创建一次。

此外,不支持集合更改中添加和删除之外的事件,但在我的情况下,我没有触发任何其他事件,因此我可以安全地忽略它们。

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 回答