В итоге я обернул объекты моей модели в объект представления, который добавляет свойство 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);
}
}
}