2013-05-11 99 views
0

我想在拖放操作过程中处理OnMouseMove或MouseWheel等事件。如何在WPF中拖放操作时处理任意事件?

但是,据我从this MSDN topic on Drag/Drop可以看出,拖放操作期间触发的唯一事件是GiveFeedback,QueryContinueDrag,Drag Enter/Leave/Over和其预览*对应项。实质上,处理这些事件可以让我获得鼠标的位置,或查看用户是否按下Ctrl,Shift,Alt,Esc或按下或释放其中一个鼠标按钮。

我想要的是在拖放操作期间处理其他事件,例如MouseWheel。具体来说,我想要做的是让用户在拖动某个窗口的同时拖动某个窗口的内容(使用鼠标滚轮)。我已经尝试为这些其他事件编写处理程序,包括冒泡和隧道版本,以及将它们附加到控制层次结构的各个层次,但据我所知,它们中没有一个正在发射。

我知道这里有一个部分解决方案(例如描述为here),当您使用DragOver滚动窗口的内容时,鼠标位置靠近窗口的顶部或底部。但那不是我想要做的。

我遇到了article,这意味着可以在拖动操作中处理(例如)OnMouseMove事件。我这样说是因为文章中的代码是上述方法的变体,但它处理的是OnMouseMove而不是DragOver。不过,我尝试调整这种方法,但仍然无法在拖动时触发OnMouseMove事件。我在下面添加了我的代码。它在F#中,所以我使用了FSharpx中的F# XAML type provider

MainWindow.xaml:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="500" Width="900"> 
    <DockPanel Name="panel1"> 
     <StatusBar Name="status1" DockPanel.Dock="Bottom"> 
      <TextBlock Name="statustext1" /> 
     </StatusBar> 
    </DockPanel> 
</Window> 

Program.fs:

(* 
Added references: PresentationCore, PresentationFramework, System.Xaml, UIAutomationTypes, WindowsBase. 
*) 

// STAThread, DateTime 
open System 
// Application 
open System.Windows 
// TextBox 
open System.Windows.Controls 

// XAML type provider 
open FSharpx 

type MainWindow = XAML<"MainWindow.xaml"> 

type TextBox2 (status : TextBlock) as this = 
    inherit TextBox() with 
    member private this.preview_mouse_left_button_down (args : Input.MouseButtonEventArgs) = do 
     this.CaptureMouse() |> ignore 
     base.OnPreviewMouseLeftButtonDown args 
// Fires while selecting text with the mouse, but not while dragging. 
    member private this.preview_mouse_move (args : Input.MouseEventArgs) = 
     if this.IsMouseCaptured then do status.Text <- sprintf "mouse move: %d" <| DateTime.Now.Ticks 
     do base.OnPreviewMouseMove args 
    member private this.preview_mouse_left_button_up (args : Input.MouseButtonEventArgs) = do 
     if this.IsMouseCaptured then do this.ReleaseMouseCapture() 
     base.OnPreviewMouseLeftButtonUp args 
    do 
     this.PreviewMouseLeftButtonDown.Add this.preview_mouse_left_button_down 
     this.PreviewMouseMove.Add this.preview_mouse_move 
     this.PreviewMouseLeftButtonUp.Add this.preview_mouse_left_button_up 

let load_window() = 
    let win = MainWindow() 
    let t = new TextBox2 (win.statustext1) 
    do 
     t.TextWrapping <- TextWrapping.Wrap 
     t.AcceptsReturn <- true 
     t.Height <- Double.NaN 
     win.panel1.Children.Add t |> ignore 
    win.Root 

[<STAThread>] 
(new Application()).Run(load_window()) |> ignore 

回答

1

我认为你可以PreviewDragEnterPreviewDragOver,并这更有效地做到。我写了一篇关于编写自己的拖放文本框的博客主题,以帮助您开始。您可以从那里添加滚动功能:

http://xcalibur37.wordpress.com/2011/12/10/wpf-drag-and-drop-textbox-for-windows-explorer-files/

代码:

/// <summary> 
/// Interaction logic for MainWindow.xaml 
/// </summary> 
public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     // Initialize UI 
     InitializeComponent(); 

     // Loaded event 
     this.Loaded += delegate 
      { 
       TextBox1.AllowDrop = true; 
       TextBox1.PreviewDragEnter += TextBox1PreviewDragEnter; 
       TextBox1.PreviewDragOver += TextBox1PreviewDragOver; 
       TextBox1.Drop += TextBox1DragDrop; 
      }; 
    } 

    /// <summary> 
    /// We have to override this to allow drop functionality. 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    void TextBox1PreviewDragOver(object sender, DragEventArgs e) 
    { 
     e.Handled = true; 
    } 

    /// <summary> 
    /// Evaluates the Data and performs the DragDropEffect 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void TextBox1PreviewDragEnter(object sender, DragEventArgs e) 
    { 
     if (e.Data.GetDataPresent(DataFormats.FileDrop)) 
     { 
      e.Effects = DragDropEffects.Copy; 
     } 
     else 
     { 
      e.Effects = DragDropEffects.None; 
     } 
    } 

    /// <summary> 
    /// The drop activity on the textbox. 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void TextBox1DragDrop(object sender, DragEventArgs e) 
    { 
     // Get data object 
     var dataObject = e.Data as DataObject; 

     // Check for file list 
     if (dataObject.ContainsFileDropList()) 
     { 
      // Clear values 
      TextBox1.Text = string.Empty; 

      // Process file names 
      StringCollection fileNames = dataObject.GetFileDropList(); 
      StringBuilder bd = new StringBuilder(); 
      foreach (var fileName in fileNames) 
      { 
       bd.Append(fileName + "\n"); 
      } 

      // Set text 
      TextBox1.Text = bd.ToString(); 
     } 
    } 
} 

的博客主题提供了各部分的破旧分析。

+1

谢谢你的回复Xcalibur。在这种情况下,我不必实现拖放功能本身,但我会在下次尝试时记住您的回复。除了DragEnter/Over/Leave/Drop事件之外,我希望做的是处理一些事件,而我正在拖动。换句话说,我想在处理拖动时处理MouseOver等任意事件。但是,这些其他事件似乎在拖曳操作过程中根本不会触发。 – FSharpN00b 2013-05-13 03:59:51