Как можно остановить разворачивание экспандера в списке при изменении данных? - PullRequest
0 голосов
/ 17 декабря 2008

У меня есть экран со списком элементов. Шаблон элемента содержит элемент управления экспандера с некоторыми данными в заголовке и некоторыми данными в контентной части экспандера.

Шаблон данных для шаблона элемента ListBox похож на этот:

<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 из-за временных ограничений

1 Ответ

0 голосов
/ 19 декабря 2008

В итоге я обернул объекты моей модели в объект представления, который добавляет свойство IsExpandable, которое я мог связать со свойством Expanded IsExpanded, а затем открыл данные.

Это не универсальное решение, но оно решает мою непосредственную проблему. Возможные проблемы, которые, как я вижу, я не исследовал, заключаются в том, что события PropertyChanged и ListChanged влекут утечки памяти с моими объектами пользовательского интерфейса, но в моей ситуации каждый объект должен создаваться только один раз.

Кроме того, события после добавления и удаления в изменении коллекции не поддерживаются, но в моем случае я больше ничего не запускаю, поэтому я могу их игнорировать.

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);
        }
    }
}
...