将 TreeViewItem 拖放到 TreeView 的不可点击区域 [WPF]

发布于 2024-11-03 05:16:45 字数 2119 浏览 0 评论 0原文

关于在 WPF 中拖放树视图项的问题。

我原来的问题有点复杂。所以我简化了它,代码如下: XAML

<Window x:Class="WpfApplication2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
<Grid>
    <TreeView>
        <TreeView.ItemContainerStyle>
            <Style>
                <Setter Property="TreeViewItem.IsExpanded" Value="True"/>
                <Setter Property="TreeViewItem.Background" Value="LightBlue"/>
                <Setter Property="TreeViewItem.AllowDrop" Value="True"/>
                <EventSetter Event="TreeViewItem.MouseMove" Handler="TreeNode_MouseMove"/>
                <EventSetter Event="TreeViewItem.Drop" Handler="TreeNode_Drop"/>
            </Style>
        </TreeView.ItemContainerStyle>

        <TreeViewItem Header="first node in the tree"/>
        <TreeViewItem Header="second node in the tree"></TreeViewItem>
        <TreeViewItem Header="third node in the tree"></TreeViewItem>
    </TreeView>
</Grid>

和代码隐藏:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void TreeNode_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            DragDrop.DoDragDrop(this, DateTime.Now.ToString(), DragDropEffects.Move);
        }
    }

    private void TreeNode_Drop(object sender, DragEventArgs e)
    {
        string str = (string)e.Data.GetData(typeof(string));
        MessageBox.Show(str);
    }
}

所以我想要做的很简单,只需将一个树视图项拖放到另一个树视图项上时弹出一个消息框即可。

当我将它放在另一个项目上时,它工作正常,如下所示:

在此处输入图像描述

但如果我稍微拖动它超出项目的边界,它不起作用,如下所示:

在此处输入图像描述

鼠标光标显示为“禁止标志”,抱歉我无法在屏幕截图中看到它。

所以现在我的问题是:如何使第二个条件成立?当放置位置稍微偏离项目边界时,如何使 Drop 事件仍然触发?

提前致谢。

A question about dragging and dropping tree view items in WPF.

My original question is a little complex. So I simplified it, and here is the code:
XAML

<Window x:Class="WpfApplication2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
<Grid>
    <TreeView>
        <TreeView.ItemContainerStyle>
            <Style>
                <Setter Property="TreeViewItem.IsExpanded" Value="True"/>
                <Setter Property="TreeViewItem.Background" Value="LightBlue"/>
                <Setter Property="TreeViewItem.AllowDrop" Value="True"/>
                <EventSetter Event="TreeViewItem.MouseMove" Handler="TreeNode_MouseMove"/>
                <EventSetter Event="TreeViewItem.Drop" Handler="TreeNode_Drop"/>
            </Style>
        </TreeView.ItemContainerStyle>

        <TreeViewItem Header="first node in the tree"/>
        <TreeViewItem Header="second node in the tree"></TreeViewItem>
        <TreeViewItem Header="third node in the tree"></TreeViewItem>
    </TreeView>
</Grid>

And code-behind:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void TreeNode_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            DragDrop.DoDragDrop(this, DateTime.Now.ToString(), DragDropEffects.Move);
        }
    }

    private void TreeNode_Drop(object sender, DragEventArgs e)
    {
        string str = (string)e.Data.GetData(typeof(string));
        MessageBox.Show(str);
    }
}

So what I want to do is very simple, just pop up a message box when one tree view item is dragged and dropped on another tree view item.

When I drop it right on another item, it works fine, like this:

enter image description here

But if I drag it slightly off the boundary of the item, it does not work, like this:

enter image description here

The mouse cursor is displayed as a “forbidden sign”, sorry I can’t get it in the screen shot.

So now my question is: how to make the second condition work? How to make the Drop event still fire up when the dropping location is slightly off the boundary of the item?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

老子叫无熙 2024-11-10 05:16:45

采用 TreeViewItem 的默认 ControlTemplate 并将 Border (包含 ContentPresenter 的边框)设置为 2 的 colspan,例如

<Border
            BorderThickness="{TemplateBinding Border.BorderThickness}"
            Padding="{TemplateBinding Control.Padding}"
            BorderBrush="{TemplateBinding Border.BorderBrush}"
            Background="{TemplateBinding Panel.Background}"
            Name="Bd"
            SnapsToDevicePixels="True"
            Grid.Column="1" Grid.ColumnSpan="2">

: TreeViewItem 中 TextBlock 旁边的整个区域将变得可点击。您可能想尝试一下该模板以适应您的需求。

在此处输入图像描述

下面是使用 转储控制模板实用程序

<?xml version="1.0" encoding="utf-16"?>
<ControlTemplate
    TargetType="TreeViewItem" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition
                Width="Auto"
                MinWidth="19" />
            <ColumnDefinition
                Width="Auto" />
            <ColumnDefinition
                Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition
                Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ToggleButton
            IsChecked="False"
            ClickMode="Press"
            Name="Expander">
            <ToggleButton.Style>
                <Style
                    TargetType="ToggleButton">
                    <Style.Resources>
                        <ResourceDictionary />
                    </Style.Resources>
                    <Setter
                        Property="UIElement.Focusable">
                        <Setter.Value>
                            <s:Boolean>False</s:Boolean>
                        </Setter.Value>
                    </Setter>
                    <Setter
                        Property="FrameworkElement.Width">
                        <Setter.Value>
                            <s:Double>19</s:Double>
                        </Setter.Value>
                    </Setter>
                    <Setter
                        Property="FrameworkElement.Height">
                        <Setter.Value>
                            <s:Double>13</s:Double>
                        </Setter.Value>
                    </Setter>
                    <Setter
                        Property="Control.Template">
                        <Setter.Value>
                            <ControlTemplate
                                TargetType="ToggleButton">
                                <Border
                                    Background="#00FFFFFF"
                                    Width="19"
                                    Height="13">
                                    <Border
                                        BorderThickness="1,1,1,1"
                                        CornerRadius="1,1,1,1"
                                        BorderBrush="#FF7898B5"
                                        Width="9"
                                        Height="9"
                                        SnapsToDevicePixels="True">
                                        <Border.Background>
                                            <LinearGradientBrush
                                                StartPoint="0,0"
                                                EndPoint="1,1">
                                                <LinearGradientBrush.GradientStops>
                                                    <GradientStop
                                                        Color="#FFFFFFFF"
                                                        Offset="0.2" />
                                                    <GradientStop
                                                        Color="#FFC0B7A6"
                                                        Offset="1" />
                                                </LinearGradientBrush.GradientStops>
                                            </LinearGradientBrush>
                                        </Border.Background>
                                        <Path
                                            Data="M0,2L0,3 2,3 2,5 3,5 3,3 5,3 5,2 3,2 3,0 2,0 2,2z"
                                            Fill="#FF000000"
                                            Name="ExpandPath"
                                            Margin="1,1,1,1" />
                                    </Border>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger
                                        Property="ToggleButton.IsChecked">
                                        <Setter
                                            Property="Path.Data"
                                            TargetName="ExpandPath">
                                            <Setter.Value>
                                                <StreamGeometry>M0,2L0,3 5,3 5,2z</StreamGeometry>
                                            </Setter.Value>
                                        </Setter>
                                        <Trigger.Value>
                                            <s:Boolean>True</s:Boolean>
                                        </Trigger.Value>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ToggleButton.Style>
        </ToggleButton>
        <Border
            BorderThickness="{TemplateBinding Border.BorderThickness}"
            Padding="{TemplateBinding Control.Padding}"
            BorderBrush="{TemplateBinding Border.BorderBrush}"
            Background="{TemplateBinding Panel.Background}"
            Name="Bd"
            SnapsToDevicePixels="True"
            Grid.Column="1">
            <ContentPresenter
                Content="{TemplateBinding HeaderedContentControl.Header}"
                ContentTemplate="{TemplateBinding HeaderedContentControl.HeaderTemplate}"
                ContentStringFormat="{TemplateBinding HeaderedItemsControl.HeaderStringFormat}"
                ContentSource="Header"
                Name="PART_Header"
                HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
                SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
        </Border>
        <ItemsPresenter
            Name="ItemsHost"
            Grid.Column="1"
            Grid.Row="1"
            Grid.ColumnSpan="2" />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger
            Property="TreeViewItem.IsExpanded">
            <Setter
                Property="UIElement.Visibility"
                TargetName="ItemsHost">
                <Setter.Value>
                    <x:Static
                        Member="Visibility.Collapsed" />
                </Setter.Value>
            </Setter>
            <Trigger.Value>
                <s:Boolean>False</s:Boolean>
            </Trigger.Value>
        </Trigger>
        <Trigger
            Property="ItemsControl.HasItems">
            <Setter
                Property="UIElement.Visibility"
                TargetName="Expander">
                <Setter.Value>
                    <x:Static
                        Member="Visibility.Hidden" />
                </Setter.Value>
            </Setter>
            <Trigger.Value>
                <s:Boolean>False</s:Boolean>
            </Trigger.Value>
        </Trigger>
        <Trigger
            Property="TreeViewItem.IsSelected">
            <Setter
                Property="Panel.Background"
                TargetName="Bd">
                <Setter.Value>
                    <DynamicResource
                        ResourceKey="{x:Static SystemColors.HighlightBrushKey}" />
                </Setter.Value>
            </Setter>
            <Setter
                Property="TextElement.Foreground">
                <Setter.Value>
                    <DynamicResource
                        ResourceKey="{x:Static SystemColors.HighlightTextBrushKey}" />
                </Setter.Value>
            </Setter>
            <Trigger.Value>
                <s:Boolean>True</s:Boolean>
            </Trigger.Value>
        </Trigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition
                    Property="TreeViewItem.IsSelected">
                    <Condition.Value>
                        <s:Boolean>True</s:Boolean>
                    </Condition.Value>
                </Condition>
                <Condition
                    Property="Selector.IsSelectionActive">
                    <Condition.Value>
                        <s:Boolean>False</s:Boolean>
                    </Condition.Value>
                </Condition>
            </MultiTrigger.Conditions>
            <Setter
                Property="Panel.Background"
                TargetName="Bd">
                <Setter.Value>
                    <DynamicResource
                        ResourceKey="{x:Static SystemColors.ControlBrushKey}" />
                </Setter.Value>
            </Setter>
            <Setter
                Property="TextElement.Foreground">
                <Setter.Value>
                    <DynamicResource
                        ResourceKey="{x:Static SystemColors.ControlTextBrushKey}" />
                </Setter.Value>
            </Setter>
        </MultiTrigger>
        <Trigger
            Property="UIElement.IsEnabled">
            <Setter
                Property="TextElement.Foreground">
                <Setter.Value>
                    <DynamicResource
                        ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
                </Setter.Value>
            </Setter>
            <Trigger.Value>
                <s:Boolean>False</s:Boolean>
            </Trigger.Value>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Take the default ControlTemplate of TreeViewItem and make the Border (the border which contains the ContentPresenter) to have a colspan of 2, e.g.:

<Border
            BorderThickness="{TemplateBinding Border.BorderThickness}"
            Padding="{TemplateBinding Control.Padding}"
            BorderBrush="{TemplateBinding Border.BorderBrush}"
            Background="{TemplateBinding Panel.Background}"
            Name="Bd"
            SnapsToDevicePixels="True"
            Grid.Column="1" Grid.ColumnSpan="2">

Note that the whole area in TreeViewItem next to the TextBlock would become clickable. You may want to play around with the template to fit it to your needs.


enter image description here

Below is the ControlTemplate of TreeViewItem extracted using Dump Control Template Utility.

<?xml version="1.0" encoding="utf-16"?>
<ControlTemplate
    TargetType="TreeViewItem" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition
                Width="Auto"
                MinWidth="19" />
            <ColumnDefinition
                Width="Auto" />
            <ColumnDefinition
                Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition
                Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ToggleButton
            IsChecked="False"
            ClickMode="Press"
            Name="Expander">
            <ToggleButton.Style>
                <Style
                    TargetType="ToggleButton">
                    <Style.Resources>
                        <ResourceDictionary />
                    </Style.Resources>
                    <Setter
                        Property="UIElement.Focusable">
                        <Setter.Value>
                            <s:Boolean>False</s:Boolean>
                        </Setter.Value>
                    </Setter>
                    <Setter
                        Property="FrameworkElement.Width">
                        <Setter.Value>
                            <s:Double>19</s:Double>
                        </Setter.Value>
                    </Setter>
                    <Setter
                        Property="FrameworkElement.Height">
                        <Setter.Value>
                            <s:Double>13</s:Double>
                        </Setter.Value>
                    </Setter>
                    <Setter
                        Property="Control.Template">
                        <Setter.Value>
                            <ControlTemplate
                                TargetType="ToggleButton">
                                <Border
                                    Background="#00FFFFFF"
                                    Width="19"
                                    Height="13">
                                    <Border
                                        BorderThickness="1,1,1,1"
                                        CornerRadius="1,1,1,1"
                                        BorderBrush="#FF7898B5"
                                        Width="9"
                                        Height="9"
                                        SnapsToDevicePixels="True">
                                        <Border.Background>
                                            <LinearGradientBrush
                                                StartPoint="0,0"
                                                EndPoint="1,1">
                                                <LinearGradientBrush.GradientStops>
                                                    <GradientStop
                                                        Color="#FFFFFFFF"
                                                        Offset="0.2" />
                                                    <GradientStop
                                                        Color="#FFC0B7A6"
                                                        Offset="1" />
                                                </LinearGradientBrush.GradientStops>
                                            </LinearGradientBrush>
                                        </Border.Background>
                                        <Path
                                            Data="M0,2L0,3 2,3 2,5 3,5 3,3 5,3 5,2 3,2 3,0 2,0 2,2z"
                                            Fill="#FF000000"
                                            Name="ExpandPath"
                                            Margin="1,1,1,1" />
                                    </Border>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger
                                        Property="ToggleButton.IsChecked">
                                        <Setter
                                            Property="Path.Data"
                                            TargetName="ExpandPath">
                                            <Setter.Value>
                                                <StreamGeometry>M0,2L0,3 5,3 5,2z</StreamGeometry>
                                            </Setter.Value>
                                        </Setter>
                                        <Trigger.Value>
                                            <s:Boolean>True</s:Boolean>
                                        </Trigger.Value>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ToggleButton.Style>
        </ToggleButton>
        <Border
            BorderThickness="{TemplateBinding Border.BorderThickness}"
            Padding="{TemplateBinding Control.Padding}"
            BorderBrush="{TemplateBinding Border.BorderBrush}"
            Background="{TemplateBinding Panel.Background}"
            Name="Bd"
            SnapsToDevicePixels="True"
            Grid.Column="1">
            <ContentPresenter
                Content="{TemplateBinding HeaderedContentControl.Header}"
                ContentTemplate="{TemplateBinding HeaderedContentControl.HeaderTemplate}"
                ContentStringFormat="{TemplateBinding HeaderedItemsControl.HeaderStringFormat}"
                ContentSource="Header"
                Name="PART_Header"
                HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
                SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
        </Border>
        <ItemsPresenter
            Name="ItemsHost"
            Grid.Column="1"
            Grid.Row="1"
            Grid.ColumnSpan="2" />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger
            Property="TreeViewItem.IsExpanded">
            <Setter
                Property="UIElement.Visibility"
                TargetName="ItemsHost">
                <Setter.Value>
                    <x:Static
                        Member="Visibility.Collapsed" />
                </Setter.Value>
            </Setter>
            <Trigger.Value>
                <s:Boolean>False</s:Boolean>
            </Trigger.Value>
        </Trigger>
        <Trigger
            Property="ItemsControl.HasItems">
            <Setter
                Property="UIElement.Visibility"
                TargetName="Expander">
                <Setter.Value>
                    <x:Static
                        Member="Visibility.Hidden" />
                </Setter.Value>
            </Setter>
            <Trigger.Value>
                <s:Boolean>False</s:Boolean>
            </Trigger.Value>
        </Trigger>
        <Trigger
            Property="TreeViewItem.IsSelected">
            <Setter
                Property="Panel.Background"
                TargetName="Bd">
                <Setter.Value>
                    <DynamicResource
                        ResourceKey="{x:Static SystemColors.HighlightBrushKey}" />
                </Setter.Value>
            </Setter>
            <Setter
                Property="TextElement.Foreground">
                <Setter.Value>
                    <DynamicResource
                        ResourceKey="{x:Static SystemColors.HighlightTextBrushKey}" />
                </Setter.Value>
            </Setter>
            <Trigger.Value>
                <s:Boolean>True</s:Boolean>
            </Trigger.Value>
        </Trigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition
                    Property="TreeViewItem.IsSelected">
                    <Condition.Value>
                        <s:Boolean>True</s:Boolean>
                    </Condition.Value>
                </Condition>
                <Condition
                    Property="Selector.IsSelectionActive">
                    <Condition.Value>
                        <s:Boolean>False</s:Boolean>
                    </Condition.Value>
                </Condition>
            </MultiTrigger.Conditions>
            <Setter
                Property="Panel.Background"
                TargetName="Bd">
                <Setter.Value>
                    <DynamicResource
                        ResourceKey="{x:Static SystemColors.ControlBrushKey}" />
                </Setter.Value>
            </Setter>
            <Setter
                Property="TextElement.Foreground">
                <Setter.Value>
                    <DynamicResource
                        ResourceKey="{x:Static SystemColors.ControlTextBrushKey}" />
                </Setter.Value>
            </Setter>
        </MultiTrigger>
        <Trigger
            Property="UIElement.IsEnabled">
            <Setter
                Property="TextElement.Foreground">
                <Setter.Value>
                    <DynamicResource
                        ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
                </Setter.Value>
            </Setter>
            <Trigger.Value>
                <s:Boolean>False</s:Boolean>
            </Trigger.Value>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
悲凉≈ 2024-11-10 05:16:45

对 TreeView 本身使用 AllowDrop 属性和 Drop 事件。

这是来自msdn:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/4b8bafe5-ae3e-439d-953a-f534a60dbb2d/

use AllowDrop property and Drop event for TreeView itself.

this is from msdn: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/4b8bafe5-ae3e-439d-953a-f534a60dbb2d/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文