WPF中控件拖放(二)——拖放示例

1.创建拖放对象

  1.1创建一个圆自定义控件,UI代码如下(Circle.xaml):  

复制代码
<UserControl x:Class="WpfApp1.Circle"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApp1"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             AllowDrop="True">
    <Grid>
        <Ellipse x:Name="circleUI" 
         Height="100" Width="100"
         Fill="Blue" />
    </Grid>
</UserControl>
复制代码

  1.2Circle.xaml.cs文件输入以下代码

    1.2.0  自定义变量声明

        /// <summary>
        /// 用于存放原有brush值,便于撤销操作
        /// </summary>
        private Brush _previousFill = null;

 

    1.2.1  添加带参数构造函数      

        public Circle(Circle c)
        {
            InitializeComponent();
            this.circleUI.Height = c.circleUI.Height;
            this.circleUI.Width = c.circleUI.Height;
            this.circleUI.Fill = c.circleUI.Fill;
        }

    1.2.2  OnMouseMove事件重写,主要是用于将圆对象数据打包到DataObject对象

复制代码
        /// <summary>
        /// 1.将圆形数据打包到 DataObject
        /// 2.调用静态 DragDrop.DoDragDrop 方法启动拖放操作
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                // Package the data.
                DataObject data = new DataObject();
                data.SetData(DataFormats.StringFormat, circleUI.Fill.ToString());
                data.SetData("Double", circleUI.Height);
                data.SetData("Object", this);

                // Initiate the drag-and-drop operation.
                DragDrop.DoDragDrop(this, data, DragDropEffects.Copy | DragDropEffects.Move);
            }
        }
复制代码

    1.2.3  自定义拖拽过程中鼠标显示样式

复制代码
        /// <summary>
        /// 设置自定义光标
        /// </summary>
        /// <param name="e"></param>
        protected override void OnGiveFeedback(GiveFeedbackEventArgs e)
        {
            base.OnGiveFeedback(e);
            // These Effects values are set in the drop target's
            // DragOver event handler.
            if (e.Effects.HasFlag(DragDropEffects.Copy))
            {
                Mouse.SetCursor(Cursors.Cross);
            }
            else if (e.Effects.HasFlag(DragDropEffects.Move))
            {
                Mouse.SetCursor(Cursors.Pen);
            }
            else
            {
                Mouse.SetCursor(Cursors.No);
            }
            e.Handled = true;
        }
复制代码

    1.2.4  处理已放置数据

复制代码
        /// <summary>
        /// 处理已放置数据
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDrop(DragEventArgs e)
        {
            base.OnDrop(e);

            // 使用 GetDataPresent 方法检查拖动的数据是否包含字符串对象
            if (e.Data.GetDataPresent(DataFormats.StringFormat))
            {
                //使用 GetData 方法提取字符串数据
                string dataString = (string)e.Data.GetData(DataFormats.StringFormat);

                //使用 BrushConverter 尝试将字符串转换为 Brush
                BrushConverter converter = new BrushConverter();
                if (converter.IsValid(dataString))
                {
                    Brush newFill = (Brush)converter.ConvertFromString(dataString);
                    //将画笔应用于提供圆形控件的 UI 的 Ellipse 的 Fill
                    circleUI.Fill = newFill;

                    // 判断是否按下ctrl键
                    if (e.KeyStates.HasFlag(DragDropKeyStates.ControlKey))
                    {
                 
复制代码

    1.2.5 验证是否允许数据放置

复制代码
        /// <summary>
        /// 验证是否允许数据放置
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDragOver(DragEventArgs e)
        {
            base.OnDragOver(e);
            e.Effects = DragDropEffects.None;

            // 使用 GetDataPresent 方法检查拖动的数据是否包含字符串对象
            if (e.Data.GetDataPresent(DataFormats.StringFormat))
            {
                //使用 GetData 方法提取字符串数据
                string dataString = (string)e.Data.GetData(DataFormats.StringFormat);

                //使用 BrushConverter 尝试将字符串转换为 Brush
                BrushConverter converter = new BrushConverter();
                if (converter.IsValid(dataString))
                {
                    Brush newFill = (Brush)converter.ConvertFromString(dataString);
                    //将画笔应用于提供圆形控件的 UI 的 Ellipse 的 Fill
                    circleUI.Fill = newFill;

                    // 判断是否按下ctrl键
                    if (e.KeyStates.HasFlag(DragDropKeyS
复制代码

    1.2.6  拖放过程中,鼠标进入后显示

复制代码
        /// <summary>
        /// 拖放鼠标进入后显示
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDragEnter(DragEventArgs e)
        {
            base.OnDragEnter(e);
            // 用于撤销操作
            _previousFill = circleUI.Fill;

            // If the DataObject contains string data, extract it.
            if (e.Data.GetDataPresent(DataFormats.StringFormat))
            {
                string dataString = (string)e.Data.GetData(DataFormats.StringFormat);

                // If the string can be converted into a Brush, convert it.
                BrushConverter converter = new BrushConverter();
                if (converter.IsValid(dataString))
                {
                    Brush newFill = (Brush)converter.ConvertFromString(dataString.ToString());
                    circleUI.Fill = newFill;
                }
            }
        }
复制代码

    1.2.7拖放过程中,鼠标离开后显示

复制代码
        /// <summary>
        /// 拖放鼠标进入后显示
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDragEnter(DragEventArgs e)
        {
            base.OnDragEnter(e);
            // 用于撤销操作
            _previousFill = circleUI.Fill;

            // If the DataObject contains string data, extract it.
            if (e.Data.GetDataPresent(DataFormats.StringFormat))
            {
                string dataString = (string)e.Data.GetData(DataFormats.StringFormat);

                // If the string can be converted into a Brush, convert it.
                BrushConverter converter = new BrushConverter();
                if (converter.IsValid(dataString))
                {
                    Brush newFill = (Brush)converter.ConvertFromString(dataString.ToString());
                    circleUI.Fill = newFill;
                }
            }
        }
复制代码

 

2.拖放具体操作实现

2.1  拖放操作实现UI,主要设置AllowDrop="True"以及设置设置相应的拖放事件

复制代码
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="0"
            Background="Beige"
            AllowDrop="True"
            DragOver="panel_DragOver"
            Drop="panel_Drop">
            <TextBox Width="Auto" Margin="2"
             Text="green"/>
            <local:Circle Margin="2" />
            <local:Circle Margin="2" />
        </StackPanel>
        <StackPanel Grid.Column="1"
            Background="Bisque"
            AllowDrop="True"
            DragOver="panel_DragOver"
            Drop="panel_Drop">
        </StackPanel>
复制代码

2.2  拖放事件具体实现

  2.2.1  拖放过程中鼠标显示形式事件实现

复制代码
        /// <summary>
        /// 拖放过程中鼠标的显示形式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void panel_DragOver(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("Object"))
            {
                // These Effects values are used in the drag source's
                // GiveFeedback event handler to determine which cursor to display.
                if (e.KeyStates == DragDropKeyStates.ControlKey)
                {
                    e.Effects = DragDropEffects.Copy;
                }
                else
                {
                    e.Effects = DragDropEffects.Move;
                }
            }
        }
复制代码

  2.2.2 拖放操作具体实现

复制代码
        /// <summary>
        /// 拖放操作具体实现
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void panel_Drop(object sender, DragEventArgs e)
        {
            //如果面板中的某个元素已经处理了放置,则面板不应同时处理该放置
            if (e.Handled == false)
            {
                Panel _panel = (Panel)sender;
                UIElement _element = (UIElement)e.Data.GetData("Object");

                if (_panel != null && _element != null)
                {
                    // 获取元素当前所属的面板,然后将其从该面板中删除,并将其添加到放置它的面板的 Children 中
                    Panel _parent = (Panel)VisualTreeHelper.GetParent(_element);

                    if (_parent != null)
                    {
                        if (e.KeyStates == DragDropKeyStates.ControlKey &&
                            e.AllowedEffects.HasFlag(DragDropEffects.Copy))
                        {
                            Circle _circle = new Circle((Circle)_element);
复制代码

 

posted @   echo-efun  阅读(152)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
点击右上角即可分享
微信分享提示