我有一个WPF TreeView
控件,它通过绑定获取分层数据。要控制控件中的可视输出,我使用Hierarchical Data Templates
。 DataContext
的{{1}}是自定义类的TreeView
,可以容纳不同类型的子类型。
ObservableCollection
由于public class PaletteGroup
{
public string Name { get; set; }
public ObservableCollection<Palette> Palettes { get; set; }
public ObservableCollection<PaletteGroup> PaletteGroups { get; set; }
public IList Children
{
get
{
return new CompositeCollection()
{
new CollectionContainer() { Collection = Palettes },
new CollectionContainer() { Collection = PaletteGroups }
};
}
}
}
public class Palette
{
public string Name { get; set; }
}
类可以容纳PaletteGroup
和Palette
类型的子项,因此我使用PaletteGroup
将CompositeCollection
组合在一个层次结构中ObservableCollection
中的视觉输出,因为我的类可以有你想要的子节点级别。
视觉输出本身在我的xaml文件中定义,我使用这两个类的TreeView
属性来显示对象的名称:
Name
正如您所看到的,我还将<local:DragDropDecorator AllowDrop="True"
AllowPaletteItems="False"
AllowPaletteGroups="True"
AllowPalettes="True">
<TreeView Margin="10,10,10,40"
Name="PaletteStructureView"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
MouseRightButtonUp="PalettesListBoxMouseRightButtonUp"
ItemsSource="{Binding LoadedPaletteGroups}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:PaletteGroup}"
ItemsSource="{Binding Children}">
<TextBlock Foreground="DarkGreen"
Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Palette}">
<TextBlock Foreground="DarkBlue"
Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</local:DragDropDecorator>
控件包装在名为TreeView
的Drag&amp; Drop操作的自定义类中,其中我在运行时添加了控件的所有必要事件。由于我使用了很多不同的控件,我厌倦了总是将事件绑定到xaml文件中的控件。此类的DragDropDecorator
事件如下所示:
Loaded
这对于private void DragableItemsControl_Loaded( object sender, RoutedEventArgs e )
{
if (!(base.DecoratedUIElement is ItemsControl))
throw new InvalidCastException(string.Format("DragDragDecorator cannot have child of type {0}", Child.GetType()));
ItemsControl itemsControl = (ItemsControl)DecoratedUIElement;
itemsControl.AllowDrop = AllowDrop;
itemsControl.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(ItemsControl_PreviewMouseLeftButtonDown);
itemsControl.PreviewMouseMove += new MouseEventHandler(ItemsControl_PreviewMouseMove);
itemsControl.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(ItemsControl_PreviewMouseLeftButtonUp);
itemsControl.PreviewDrop += new DragEventHandler(ItemsControl_PreviewDrop);
itemsControl.PreviewQueryContinueDrag += new QueryContinueDragEventHandler(ItemsControl_PreviewQueryContinueDrag);
itemsControl.PreviewDragEnter += new DragEventHandler(ItemsControl_PreviewDragEnter);
itemsControl.PreviewDragOver += new DragEventHandler(ItemsControl_PreviewDragOver);
itemsControl.DragLeave += new DragEventHandler(ItemsControl_DragLeave);
}
控件来说绝对正常,这也是我项目的需要。但是我对ListBox
控件非常困难,因为事件仅针对TreeView
中的最高节点引发,即使我尝试对某些孩子进行拖放操作。
首先,我尝试将所有事件添加到TreeView
。这适用于第一级子节点,但忽略更深的节点结构以及最上面的节点。
然后我尝试将所有事件添加到TreeView.ItemContainerStyle
类的Hierarchical Data Template
事件中的Loaded
:
DragDropDecorator
使用此代码,由于已经密封的模板对象,我得到if (itemsControl.GetType() == typeof(TreeView))
{
foreach (object item in itemsControl.Resources.Keys)
{
var hdt = itemsControl.FindResource(item);
if (hdt != null & hdt.GetType() == typeof(HierarchicalDataTemplate))
{
var newHdt = (HierarchicalDataTemplate)hdt;
var test = new Style();
test.Setters.Add(new EventSetter(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(ItemsControl_PreviewMouseLeftButtonDown)));
test.Setters.Add(new EventSetter(PreviewMouseMoveEvent, new MouseEventHandler(ItemsControl_PreviewMouseMove)));
test.Setters.Add(new EventSetter(PreviewMouseLeftButtonUpEvent, new MouseButtonEventHandler(ItemsControl_PreviewMouseLeftButtonUp)));
test.Setters.Add(new EventSetter(PreviewDropEvent, new DragEventHandler(ItemsControl_PreviewDrop)));
test.Setters.Add(new EventSetter(PreviewQueryContinueDragEvent, new QueryContinueDragEventHandler(ItemsControl_PreviewQueryContinueDrag)));
test.Setters.Add(new EventSetter(PreviewDragEnterEvent, new DragEventHandler(ItemsControl_PreviewDragEnter)));
test.Setters.Add(new EventSetter(PreviewDragOverEvent, new DragEventHandler(ItemsControl_PreviewDragOver)));
test.Setters.Add(new EventSetter(DragLeaveEvent, new DragEventHandler(ItemsControl_DragLeave)));
newHdt.ItemContainerStyle = test;
}
}
}
。
所以我的问题是:
InvalidOperationException
? 经过几个小时尝试不同的方法并在互联网上搜索解决方案后,我现在被困住了。如果有人可以指出我正确的方向,甚至给我写一些代码片段,这将有助于我回到正轨,我将不胜感激。
我希望我发布的代码足够了。如果没有,只需发表评论,我将添加其他部分。
提前感谢您的时间!
答案 0 :(得分:0)
我自己解决了这个问题,我想在这里发布代码以供将来参考。也许这不是最好的解决方案,但它对我有用。我在currentUser
类的Loaded
事件中添加了以下行:
DragDropDecorator
我无法编辑样式,因为它一旦设置就会被密封。所以我在新样式对象上使用了if (itemsControl.GetType() == typeof(TreeView))
{
var originalStyle = itemsControl.Style;
var newStyle = new Style();
newStyle.BasedOn = originalStyle;
newStyle.Setters.Add(new EventSetter(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(ItemsControl_PreviewMouseLeftButtonDown)));
newStyle.Setters.Add(new EventSetter(PreviewMouseMoveEvent, new MouseEventHandler(ItemsControl_PreviewMouseMove)));
newStyle.Setters.Add(new EventSetter(PreviewMouseLeftButtonUpEvent, new MouseButtonEventHandler(ItemsControl_PreviewMouseLeftButtonUp)));
newStyle.Setters.Add(new EventSetter(PreviewDropEvent, new DragEventHandler(ItemsControl_PreviewDrop)));
newStyle.Setters.Add(new EventSetter(PreviewQueryContinueDragEvent, new QueryContinueDragEventHandler(ItemsControl_PreviewQueryContinueDrag)));
newStyle.Setters.Add(new EventSetter(PreviewDragEnterEvent, new DragEventHandler(ItemsControl_PreviewDragEnter)));
newStyle.Setters.Add(new EventSetter(PreviewDragOverEvent, new DragEventHandler(ItemsControl_PreviewDragOver)));
newStyle.Setters.Add(new EventSetter(DragLeaveEvent, new DragEventHandler(ItemsControl_DragLeave)));
itemsControl.ItemContainerStyle = newStyle;
}
属性,以获取已设置的样式信息,添加BasedOn
并将新样式应用于EventSetter
。