65.9K
CodeProject 正在变化。 阅读更多。
Home

[技巧] 监听你的 DragEventArgs!

starIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

1.00/5 (1投票)

2017年4月11日

CPOL

2分钟阅读

viewsIcon

11463

如何通过多个对象连接拖放事件。

问题

在代码后处理几乎任何事情都是不好的(通常来说),并且很容易创建紧密耦合的依赖关系。 在代码后处理事件,例如拖放,更容易产生这些依赖关系。

那么,如果不在代码后处理中,该如何处理拖放事件呢?

解决方案(示例代码)

快速说明 - 我刚刚弄清楚了这一点,想分享一下! 很有可能还有更好的方法来处理或解决这个问题,所以如果你知道任何方法,请在评论中告诉我。

 

我发现示例是解释概念的最佳方式。 假设你有一个 UserControl,我们称之为 MyView,它定义了初始的拖放事件。 我们还有主窗口类(MainWindow),它将 MyView 作为子元素。 在这个例子中,MainWindow 将监听 MyViewDrop 事件,并随后调用其 ViewModelMainWindowViewModel)的方法来处理逻辑。

请记住,这个技巧/窍门的重点 是展示如何 启用监听 使用 DragEventArgs 的事件(例如 Drop 或 DragEnter)。 你实际从哪里监听是取决于你的。

UserControl MyView

MyView.xaml
<UserControl x:Class="MyProject.Views.MyView"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             x:Name="uc_View">
    <Grid>
        <ListBox Name="lbxView" AllowDrop="True" Drop="lbxView_Drop">
            <!-- Add listbox content here -->
        </ListBox>
    </Grid>
</UserControl>

关键代码

AllowDrop 基本上启用拖放功能。

Drop 是我们在拖放事件发生时调用方法名称的地方。

 

MyView.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;

namespace MyProject.Views
{
    /// <summary>
    /// Interaction logic for MyView.xaml
    /// </summary>
    public partial class MyView : UserControl
    {
        // Define an 'EventHandler' for an object to listen to.
        // The name doesn't really matter, just know that this is what other
        // objects will reference when adding their listener.
        public event EventHandler<DragEventArgs> ObjectDropped;
        
        // Define how to invoke/call this event
        protected virtual void OnObjectDropped(DragEventArgs e)
        {
            ObjectDropped?.Invoke(this, e);
        }
        
        // Define the drop method that we specified in the MyView.xaml file
        private void lbxView_Drop(object sender, DragEventArgs e)
        {
            OnObjectDropped(sender, e);
        }
    }
}

关键代码

EventHandler<> 我们需要使用 EventHandler 的模板版本才能使其工作。 这也是其他对象添加其监听方法的公共句柄。

lbxView_Drop 在拖放事件发生时触发,并基本上调用监听委托。

 

Window MainWindow

MainWindow.xaml
<Window x:Class="MyProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MyProject"
        xmlns:localViews="clr-namespace:MyProject.Views"
        Title="MyApp" Height="500" Width="720">
    <Grid>
        <localViews:MyView x:Name="myView" ObjectDropped="MyView_ObjectDropped"/>
    </Grid>
</Window>

关键代码

ObjectDropped 是我之前提到的公共事件句柄。 你可以在这里传递监听方法名称。

MainWindow.xaml.cs
using System.Windows;
using MyProject.ViewModels;

namespace MyProject
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // Just for a simple demonstration of passing the logic to the ViewModel
        private MainWindowViewModel _viewModel;
        
        private void MyView_ObjectDropped(object sender, DragEventArgs e)
        {
            // Handle the drop logic here!
            // Example:
            _viewModel.ObjectDropped( sender, e );
        }
    }
}

这里没有真正关键的代码,主要是为了完整性。 是的,ViewModel 的处理可以抽象出来,但这超出了本文的范围。


Window MainWindow(备选方案)

我强烈建议不要这样做,但我知道对于其他人来说,这可能是最佳选择。

你可以添加监听器的另一种方法是省略 MainWindow.xaml 中的 ObjectDropped="MyView_ObjectDropped",并在 MainWindow 的构造函数中添加监听器。

MainWindow.xaml.cs(备选方案)
using System.Windows;

namespace MyProject
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            myView.ObjectDropped += new EventHandler<DragEventArgs>(MyView_ObjectDropped);
        }
            
        private void MyView_ObjectDropped(object sender, DragEventArgs e)
        {
            // Handle the drop logic here!
        }
    }
}
© . All rights reserved.