WPFコントロールのドラッグ/ドロップエフェクトを[なし]に設定して、線記号付きのサークルを表示する方法を見つけることができます。ここでWPFドラッグドロップなし効果トリガーなし
はそれが仕事を得るためにそれを修正し、私は様々な例からコピーしたコードです:
これは、Windowの背後にあるコードです:
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;
}
}
}
}
}
そして、ここではそのための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>
...それらのすべてが正常に動作、および/上下スクロールの基本的な考え方:それは適切なイベントに登録されていることを示しますドラッグしながらブロック内のアイテムを交換するとすべてうまく動作します。
しかし、愚かなアイコンは私のために変更を拒否します。 :)
ハンドラの一番上でNoneに設定しようとしましたが、親が同じであればAllowedEffectsに戻すようにしました。
基本的に、アイコンは...同じではありません親にドラッグする場合は、それを通る線と円(なし)に
を切り替える必要があり、私もそれが入るされることを保証するためにブレークポイントを設定しています両親が同じではなく、その効果をNoneに設定したケース。どういうわけか、何かそれを元に戻す必要がありますが、私は何も考えていません...
したがって、DragOverおよびDragEnterイベントハンドラでは、単にe.Effects = DragDropEffects.Noneを設定するだけで、アイコンは変更されません。私はトンネルイベントハンドラの代わりにプレビューイベントハンドラとして試してみましたが、動作しません。私はまた、両方のバージョンのイベントハンドラを何もしないでe.Effects = DragDropEffects.Noneを設定することを試みたが、アイコンは変更されません... – cwodarczyk82