【发布时间】:2014-08-15 21:46:11
【问题描述】:
我试图让 TreeView 工作,它使用 HierarchialDataTemplate 将节点绑定到 ObservableCollection。 TreeViewItems 是其中包含复选框和组合框的网格。所有这些都可以正常工作,但我没有设法让拖放功能正常工作。
代码基于 TreeView, HierarchicalDataTemplate and recursive Data 和 http://www.codeproject.com/Articles/55168/Drag-and-Drop-Feature-in-WPF-TreeView-Control
<Window x:Class="TreeView_HierarchicalDataTemplate.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:TreeView_HierarchicalDataTemplate="clr-namespace:TreeView_HierarchicalDataTemplate"
Title="MainWindow" x:Name="mainWindow" Height="350" Width="525">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</Window.Resources>
<Grid>
<TreeView Name="TreeView_After" AllowDrop="True" DataContext="{Binding ElementName=mainWindow, Path=TreeModel}" ItemsSource="{Binding Items}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<EventSetter Event="TreeViewItem.DragOver" Handler="TreeView_After_DragOver"/>
<EventSetter Event="TreeViewItem.Drop" Handler="TreeView_After_Drop"/>
<EventSetter Event="TreeViewItem.MouseMove" Handler="TreeView_After_MouseMove"/>
<EventSetter Event="TreeViewItem.MouseDown" Handler="TreeView_After_MouseDown"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type TreeView_HierarchicalDataTemplate:NodeViewModel}" ItemsSource="{Binding Children}">
<Grid Background="LightBlue">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Name}"></TextBlock>
<GridSplitter Visibility="{Binding Path=Show, Converter={StaticResource BoolToVis}}" Grid.Column="0" Width="5"/>
<CheckBox Visibility="{Binding Path=Show, Converter={StaticResource BoolToVis}}" Grid.Row="0" Grid.Column="1" Margin="5,5,0,0">activated</CheckBox>
<GridSplitter Visibility="{Binding Path=Show, Converter={StaticResource BoolToVis}}" Grid.Column="0" Width="5"/>
<StackPanel Visibility="{Binding Path=Show, Converter={StaticResource BoolToVis}}" Grid.Row="0" Grid.Column="2" Orientation="Horizontal">
<TextBlock Margin="5">Action:</TextBlock>
<ComboBox>
<TextBlock>Move To</TextBlock>
</ComboBox>
<TextBlock Margin="5">C:\\Videos\Folder\aVideo.mkv</TextBlock>
</StackPanel>
<GridSplitter Visibility="{Binding Path=Show, Converter={StaticResource BoolToVis}}" Grid.Column="1" Width="5"/>
<StackPanel Visibility="{Binding Path=Show, Converter={StaticResource BoolToVis}}" Grid.Row="0" Grid.Column="3" Orientation="Horizontal">
<TextBlock Margin="5">Duplicate of:</TextBlock>
<ComboBox>
<TextBlock>None</TextBlock>
</ComboBox>
</StackPanel>
</Grid>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
这是 Observable 集合
public class TreeViewModel
{
public ObservableCollection<NodeViewModel> Items { get; set; }
}
public class NodeViewModel : UIElement
{
public NodeViewModel()
{
Show = true;
}
public string Id { get; set; }
public string Name { get; set; }
public bool Show { get; set; }
public ObservableCollection<NodeViewModel> Children { get; set; }
}
但是这个鼠标按下事件不起作用
private void TreeView_After_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
_lastMouseDown = e.GetPosition(TreeView_After);
}
}
此外,如果我从 UIElement 派生 NodeViewModel,我只有从元素(UIElement)到容器(NodeViewModel)的这种类型转换才能工作。但是,如果我从 UIElement 派生 NodeViewModel,TreeView 将不再显示:(
private NodeViewModel GetNearestContainer(UIElement element)
{
// Walk up the element tree to the nearest tree view item.
NodeViewModel container = element as NodeViewModel;
while ((container == null) && (element != null))
{
element = VisualTreeHelper.GetParent(element) as UIElement;
container = element as NodeViewModel;
}
return container;
}
【问题讨论】: