下面是最基本的問題:我如何偵聽通過DragDropTarget修改的TreeView控件中更改內容的更新?使用DragDropTarget對Silverlight TreeView上的ObservableCollection進行雙向數據綁定
所以這裏是我的交易:我有一個TreeView持有議程項目。所有的數據類型都是相同的(WCFAgendaItem),並且被加載到一個層次結構中,子層表示爲屬性ChildItems。整個事情被封裝在一個ObservableCollection中,並使用MVVM Light綁定到TreeView。非常適合查看。我還希望用戶能夠使用拖放來重新排序,重新組織和添加來自各種其他來源(例如圖像幻燈片的ListView)的此議程的新項目。爲了一致性和簡單的序列化,所有新項目也將具有相同的WCFAgendaItem數據類型。
這是我的問題:使用工具包的拖放功能,拖放功能可以在UI上精美地工作。但我不知道如何讓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>
視圖模型碼(AgendaViewModel.cs) - >我試着收聽CollectionChanged,到目前爲止似乎沒有工作
(在構造函數中)
//add notification of agenda changes
DailyAgenda.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(DailyAgenda_CollectionChanged);
(事件)從模型(WCFAgendaItem.cs)
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.");
}
代碼
[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在任何情況下是不正確的,因爲這些數據不僅僅在最高層發生變化。我看着Blend中的EventToCommand(記住MVVM Light),但是唯一的TreeView特定的事件看起來像是SelectionChanged,看起來也不錯。我研究了在TreeViewDragDropTarget上放置EventToCommand觸發器,但是不是那些覆蓋UI交互發生的方法嗎?我不認爲WCFAgendaItem上的INotifyPropertyChanged適合這種情況:儘管稍後我會希望用它來編輯項目標題,但當項目移動時,它似乎不會幫助我。
也許我在尋找的是一種延伸,但我真正想要發生的是讓Silverlight理解數據綁定對WCFAgendaItem集合的排序和內容都起作用,並且執行所有集合重構本身基於UI交互。然後我可以在集合被重寫之後監聽更新事件 - 之後,我可以將修改的ObservableCollection綁定到TreeView,並通過WCF對其進行平鋪/序列化/更新。
失敗的理想情況:我願意抓取TreeViewItems,如果需要的話,但即使這就是我需要做的事情,我堅持什麼時候去做。另外我需要一種方法將所有返回給ViewModel,所以我不寫代碼。我是否需要附加到Drop()並重寫刪除邏輯?我發現了幾篇關於從Toolkit開始的自定義拖放實現的舊文章,但沒有人提到如何將修改過的TreeView保存出來,尤其是在MVVM情況下。
終於{
雖然打字了這一點,我發現this article這可能是有用的,儘管這在視圖模型的工作相當數量。這是有希望的,我會進行調查,但我仍然抱着更簡單的希望。自文章寫入以來,它看起來似乎工具包事件發生了一些變化。
}