因此,我几乎遵循了我能找到的所有示例,了解如何将 WPF 控件上的拖/放效果设置为“无”以显示带有线条符号的圆圈,但无济于事。
这是我从各种示例中复制的代码,对其进行修改以使其正常工作:
这是窗口背后的代码:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace TreeViewWithCheckBoxes
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
FooViewModel root = this.tree.Items[0] as FooViewModel;
base.CommandBindings.Add(
new CommandBinding(
ApplicationCommands.Undo,
(sender, e) => // Execute
{
e.Handled = true;
root.IsChecked = false;
this.tree.Focus();
},
(sender, e) => // CanExecute
{
e.Handled = true;
e.CanExecute = (root.IsChecked != false);
}));
this.tree.Focus();
}
private void TreeViewItemDragEnter(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.None;
if (e.Data.GetDataPresent(typeof(FooViewModel)))
{
var folderViewModel = e.Data.GetData(typeof(FooViewModel))
as FooViewModel;
var treeViewItem =
VisualTreeHelperUtils.FindParent<TreeViewItem>
((DependencyObject)e.OriginalSource);
if (treeViewItem == null)
{
return;
}
var dropTarget = treeViewItem.Header as FooViewModel;
if (dropTarget == null || folderViewModel == null)
{
return;
}
if (dropTarget.Parent == folderViewModel.Parent)
e.Effects = e.AllowedEffects;
else
{
e.Effects = DragDropEffects.None;
}
}
}
private void TreeViewItemDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(FooViewModel)))
{
var folderViewModel = e.Data.GetData(typeof(FooViewModel))
as FooViewModel;
var treeViewItem =
VisualTreeHelperUtils.FindParent<TreeViewItem>
((DependencyObject)e.OriginalSource);
var dropTarget = treeViewItem.Header as FooViewModel;
if (dropTarget == null || folderViewModel == null)
return;
if (dropTarget.Parent == folderViewModel.Parent)
{
var dropType = dropTarget.Name;
var dragType = folderViewModel.Name;
var parent = dropTarget.Parent;
if (parent != null)
{
var dropLocation = -1;
var dragLocation = -1;
for (int index = 0; index < parent.Children.Count; ++index)
{
if (parent.Children[index].Name == dropType) dropLocation = index;
if (parent.Children[index].Name == dragType) dragLocation = index;
if (dropLocation != -1 && dragLocation != -1)
break;
}
if (dropLocation != -1 && dragLocation != -1)
{
parent.Children[dropLocation] = folderViewModel;
parent.Children[dragLocation] = dropTarget;
}
}
}
}
}
private void TreeViewItemMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var mousePos = e.GetPosition(null);
var diff = StartPoint - mousePos;
if (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance
|| Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)
{
var treeView = sender as TreeView;
var treeViewItem =
VisualTreeHelperUtils.FindParent<TreeViewItem>((DependencyObject)e.OriginalSource);
if (treeView == null || treeViewItem == null)
return;
var folderViewModel = treeView.SelectedItem as FooViewModel;
if (folderViewModel == null)
return;
var dragData = new DataObject(folderViewModel);
DragDrop.DoDragDrop(treeViewItem, dragData, DragDropEffects.Move);
}
}
}
private void TreeViewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
StartPoint = e.GetPosition(null);
}
public Point StartPoint { get; set; }
private void TreeViewItemDragOver(object sender, DragEventArgs e)
{
var container = sender as FrameworkElement;
if (container == null)
{
return;
}
var scrollViewer = VisualTreeHelperUtils.GetFirstVisualChild<ScrollViewer>(container);
if (scrollViewer == null)
{
return;
}
double tolerance = 30;
double verticalPos = e.GetPosition(container).Y;
double offset = 20;
if (verticalPos < tolerance) // Top of visible list?
{
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - offset); //Scroll up.
}
else if (verticalPos > container.ActualHeight - tolerance) //Bottom of visible list?
{
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset); //Scroll down.
}
e.Effects = DragDropEffects.None;
var source = e.OriginalSource as DependencyObject;
if (source == null)
{
return;
}
if (e.Data.GetDataPresent(typeof(FooViewModel)))
{
var folderViewModel = e.Data.GetData(typeof(FooViewModel))
as FooViewModel;
var treeViewItem =
VisualTreeHelperUtils.FindParent<TreeViewItem>((DependencyObject)e.OriginalSource);
if (treeViewItem == null)
{
return;
}
var dropTarget = treeViewItem.Header as FooViewModel;
if (dropTarget == null || folderViewModel == null)
{
return;
}
if (dropTarget.Parent == folderViewModel.Parent)
e.Effects = e.AllowedEffects;
else
{
e.Effects = DragDropEffects.None;
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
下面是它的 XAML,显示它已注册了正确的事件:
<Window
x:Class="TreeViewWithCheckBoxes.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TreeViewWithCheckBoxes"
xmlns:dw="clr-namespace:DrWPF.Windows.Controls"
FontSize="13"
Title="TreeView with CheckBoxes"
Width="300" Height="300"
WindowStartupLocation="CenterScreen"
>
<Window.Resources>
<ResourceDictionary>
<!-- Load this specific theme because the Aero theme for CheckBox has issues. -->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/PresentationFramework.Royale;V3.0.0.0;31bf3856ad364e35;component\themes\royale.normalcolor.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="TreeViewItemStyle" TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
<Setter Property="IsSelected" Value="{Binding IsInitiallySelected, Mode=OneTime}" />
<Setter Property="KeyboardNavigation.AcceptsReturn" Value="True" />
<Setter Property="dw:VirtualToggleButton.IsVirtualToggleButton" Value="True" />
<Setter Property="dw:VirtualToggleButton.IsChecked" Value="{Binding IsChecked}" />
</Style>
<HierarchicalDataTemplate
x:Key="CheckBoxItemTemplate"
ItemsSource="{Binding Children, Mode=OneTime}"
>
<StackPanel Orientation="Horizontal">
<!-- These elements are bound to a FooViewModel object. -->
<CheckBox
Focusable="False"
IsChecked="{Binding IsChecked}"
VerticalAlignment="Center"
/>
<ContentPresenter
Content="{Binding Name, Mode=OneTime}"
Margin="2,0"
/>
</StackPanel>
</HierarchicalDataTemplate>
</ResourceDictionary>
</Window.Resources>
<Window.DataContext>
<ObjectDataProvider
MethodName="CreateFoos"
ObjectType="{x:Type local:FooViewModel}" />
</Window.DataContext>
<TabControl>
<TabItem Header="Original">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
<RowDefinition Height=".2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button
Grid.Row="3"
Command="Undo"
Content="Generate Report"
HorizontalAlignment="Center"
Margin="0,2"
Padding="8,0"
/>
<TreeView
Grid.Row="0"
x:Name="tree"
ItemContainerStyle="{StaticResource TreeViewItemStyle}"
ItemsSource="{Binding Mode=OneTime}"
ItemTemplate="{StaticResource CheckBoxItemTemplate}"
AllowDrop="True"
PreviewMouseLeftButtonDown="TreeViewMouseLeftButtonDown"
PreviewMouseMove="TreeViewItemMouseMove"
DragEnter="TreeViewItemDragEnter"
DragOver="TreeViewItemDragOver"
Drop="TreeViewItemDrop"
/>
<ScrollViewer Grid.Row="2" IsEnabled="{Binding ElementName=tree, Path=SelectedItem.IsChecked}">
<TextBlock Text="Oh Hai"></TextBlock>
<ScrollViewer.Style>
<Style TargetType="ScrollViewer">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5"></Setter>
<Setter Property="VerticalScrollBarVisibility" Value="Hidden"></Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Opacity" Value="1"></Setter>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ScrollViewer.Style>
</ScrollViewer>
</Grid>
</TabItem>
<TabItem Header="Modified">
<DockPanel>
<Button
DockPanel.Dock="Bottom"
Command="Undo"
Content="Uncheck All"
HorizontalAlignment="Center"
Margin="0,2"
Padding="8,0"
/>
<TreeView
x:Name="modified"
ItemContainerStyle="{StaticResource TreeViewItemStyle}"
ItemsSource="{Binding Mode=OneTime}"
ItemTemplate="{StaticResource CheckBoxItemTemplate}"
/>
</DockPanel>
</TabItem>
</TabControl>
</Window>
Run Code Online (Sandbox Code Playgroud)
我没有为辅助方法附加任何代码......这些都工作得很好,并且在拖动时向上/向下滚动以及交换块内的项目的基本思想都工作得很好。
然而,这个愚蠢的图标拒绝为我改变。:)
我什至尝试在处理程序的最顶部将其设置为 None,并且仅在父母相同的情况下将其设置回 AllowedEffects。
本质上,如果拖动到不相同的父级,图标应该切换到有线穿过的圆圈(无)...
我什至设置了断点以确保它进入父母不相同的情况并将效果设置为“无”。不知何故,一定有什么东西把它切换回来,但我不知道是什么......
| 归档时间: |
|
| 查看次数: |
1813 次 |
| 最近记录: |