Вот основной вопрос: как мне прослушать обновление изменений в элементе управления TreeView, измененном с помощью DragDropTarget?
Итак, вот мое предложение: у меня естьTreeView, который содержит пункты повестки дня.Все они имеют один и тот же тип данных (WCFAgendaItem) и загружаются в иерархию с дочерними элементами, выраженными как свойство ChildItems.Все это заключено в ObservableCollection и привязано к TreeView с помощью MVVM Light.Прекрасно работает для просмотра.Я также хочу, чтобы пользователи могли использовать перетаскивание для изменения порядка, реорганизации и добавления новых элементов в эту повестку дня из различных других источников (одним из примеров является ListView слайдов изображений).Все новые элементы также будут иметь один и тот же тип данных WCFAgendaItem для обеспечения согласованности и упрощения сериализации.
Вот моя проблема: перетаскивание прекрасно работает в пользовательском интерфейсе с использованием функциональности перетаскивания в наборе инструментов.Но я понятия не имею, как заставить ViewModel понимать изменения в содержимом TreeView.
Код из представления (Agenda.xaml):
(вверх)
<UserControl.Resources>
<AHHSTeam_SLClassroomManagerMVVM_Helpers_Converters:BooleanVisibilityConverter x:Key="BooleanVisibilityConverter"/>
<sdk:HierarchicalDataTemplate x:Key="hdtAgenda" ItemsSource="{Binding ChildItems, Mode=TwoWay}" >
<Grid HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ImageThumbnailWidth}" />
<ColumnDefinition Width="250" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding ThumbnailURL}" Width="{Binding ImageThumbnailWidth}" Height="{Binding ImageThumbnailHeight}" Visibility="{Binding HasImage, Converter={StaticResource BooleanVisibilityConverter}}" >
<ToolTipService.ToolTip>
<Image Source="{Binding ResizedImageURL}" />
</ToolTipService.ToolTip>
</Image>
<TextBlock Grid.Column="1" Text="{Binding Title}" TextWrapping="Wrap" />
</Grid>
</sdk:HierarchicalDataTemplate>
<Style TargetType="sdk:TreeViewItem" >
<Setter Property="IsExpanded" Value="True" />
</Style>
</UserControl.Resources>
(позже)
<controlsToolkit:TreeViewDragDropTarget Grid.Row="1" Grid.Column="0" x:Name="ddtAgenda" AllowDrop="True"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" >
<sdk:TreeView Width="375" ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Visible" ItemsSource="{Binding DailyAgenda, Mode=TwoWay}" ItemTemplate="{StaticResource hdtAgenda}">
</sdk:TreeView>
</controlsToolkit:TreeViewDragDropTarget>
Код ViewModel (AgendaViewModel.cs) -> Я пытался прослушивать CollectionChanged, но пока что он не работает
(в конструкторе)
//add notification of agenda changes
DailyAgenda.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(DailyAgenda_CollectionChanged);
(событие)
void DailyAgenda_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
System.Windows.MessageBox.Show("Daily agenda updated, now has " + e.NewItems.Count.ToString() + " top-level elements.");
}
Код из модели (WCFAgendaItem.cs)
[ContentProperty("ChildItems")]
public partial class WCFAgendaItem: INotifyPropertyChanged
{
private ObservableCollection<WCFAgendaItem> _childItems = new ObservableCollection<WCFAgendaItem>();
public ObservableCollection<WCFAgendaItem> ChildItems
{
get
{
return _childItems;
}
set
{
_childItems = value;
}
}
...
Я почти уверен, что получаю прослушиваниедля CollectionChanged не подходит ни в коем случае, учитывая, что эти данные не просто изменяются на верхнем уровне.Я посмотрел на EventToCommand в Blend (MVVM Light, помните), но единственное специфичное для TreeView событие - это SelectionChanged, что тоже не совсем правильно.Я смотрел на помещение триггера EventToCommand на TreeViewDragDropTarget, но разве эти методы не переопределяют, как происходят взаимодействия с пользовательским интерфейсом?Я не думаю, что INotifyPropertyChanged для WCFAgendaItem также подходит для этого: хотя я хочу, чтобы позже это понадобилось для редактирования названий элементов, не похоже, что это поможет мне, когда элементы будут перемещаться.
Может быть, то, что я ищу, - это растяжка, но я действительно хочу, чтобы Silverlight понял, что привязка данных работает в обоих направлениях при упорядочении и содержимом коллекции WCFAgendaItem, и выполняет всю работу по переработке самой коллекции на основеUI взаимодействияТогда я мог бы просто прослушать событие обновления после того, как коллекция была переработана - после этого я могу просто отсканировать измененную коллекцию ObservableCollection, привязанную к TreeView, и сгладить / сериализовать / обновить через WCF.
В противном случае идеальная ситуация: IЯ хочу сканировать TreeViewItems, если это необходимо, но даже если это то, что мне нужно сделать, я застрял, когда это сделать.Кроме того, мне нужен способ передать все это обратно в ViewModel, чтобы я не писал код позади.Нужно ли присоединяться к Drop () и переделывать логику удаления?Я нашел несколько старых статей о пользовательских реализациях перетаскивания, начиная с Toolkit, но никто не упоминает, как сохранить измененный TreeView, особенно в ситуации MVVM.
finally {
При вводе этогоЯ нашел эту статью , которая может быть полезной, хотя в ViewModel это довольно много работы.Это многообещающе, и я буду исследовать, но я все еще надеюсь на что-то более простое.Также похоже, что события Toolkit немного изменились с момента написания статьи.
}