Ale*_*x K 104 c# wpf user-interface drag-and-drop
我的问题是2倍,我希望WPF提供的解决方案更容易,而不是WinForms的标准解决方案(在我做出澄清之前Christophe Geers提供的解决方案).
首先,有没有一种方法可以在不捕获和处理鼠标点击+拖动事件的情况下使窗口可拖动?我的意思是窗口可以通过标题栏拖动,但如果我设置一个窗口没有一个并且仍然希望能够拖动它,有没有办法只是将事件重新指向任何处理标题栏拖动的处理?
第二,有没有办法将事件处理程序应用于窗口中的所有元素?同样,无论用户点击哪个元素+拖动,都可以使窗口可拖动.显然,没有手动添加处理程序,每个元素.在某个地方做一次吗?
Rac*_*hel 267
当然,申请以下MouseDown事件Window
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
this.DragMove();
}
Run Code Online (Sandbox Code Playgroud)
这将允许用户在任何控件上单击/拖动时拖动窗口,对于吃掉MouseDown事件的控件e.Handled = true除外()
您可以使用PreviewMouseDown而不是MouseDown,但拖动事件会占用Click事件,因此您的窗口会停止响应鼠标左键单击事件.如果您真的希望能够从任何控件单击并拖动窗体,您可以使用PreviewMouseDown,启动计时器以开始拖动操作,并在MouseUp事件在X毫秒内触发时取消操作.
如果wpf表单需要可拖动而不管它被点击的位置,那么简单的解决方法是使用委托来触发windows onload事件或网格加载事件上的DragMove()方法
private void Grid_Loaded(object sender, RoutedEventArgs
{
this.MouseDown += delegate{DragMove();};
}
Run Code Online (Sandbox Code Playgroud)
小智 6
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
this.DragMove();
}
Run Code Online (Sandbox Code Playgroud)
在某些情况下会引发异常(即,如果窗口上还有一个可单击的图像,单击该图像会打开一个消息框。当您从消息框退出时,您会收到错误消息)使用起来更安全
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
this.DragMove();
}
Run Code Online (Sandbox Code Playgroud)
所以你确定当时按下了左按钮。
有时,我们无法访问Window,例如,如果我们正在使用DevExpress,则所有可用的是UIElement。
解决办法是:
MouseMove事件挂钩;Window;.DragMove()我们新发现的Window。代码:
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace DXApplication1.AttachedProperty
{
public class EnableDragHelper
{
public static readonly DependencyProperty EnableDragProperty = DependencyProperty.RegisterAttached(
"EnableDrag",
typeof (bool),
typeof (EnableDragHelper),
new PropertyMetadata(default(bool), OnLoaded));
private static void OnLoaded(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var uiElement = dependencyObject as UIElement;
if (uiElement == null || (dependencyPropertyChangedEventArgs.NewValue is bool) == false)
{
return;
}
if ((bool)dependencyPropertyChangedEventArgs.NewValue == true)
{
uiElement.MouseMove += UIElementOnMouseMove;
}
else
{
uiElement.MouseMove -= UIElementOnMouseMove;
}
}
private static void UIElementOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
var uiElement = sender as UIElement;
if (uiElement != null)
{
if (mouseEventArgs.LeftButton == MouseButtonState.Pressed)
{
DependencyObject parent = uiElement;
int avoidInfiniteLoop = 0;
// Search up the visual tree to find the first parent window.
while ((parent is Window) == false)
{
parent = VisualTreeHelper.GetParent(parent);
avoidInfiniteLoop++;
if (avoidInfiniteLoop == 1000)
{
// Something is wrong - we could not find the parent window.
return;
}
}
var window = parent as Window;
window.DragMove();
}
}
}
public static void SetEnableDrag(DependencyObject element, bool value)
{
element.SetValue(EnableDragProperty, value);
}
public static bool GetEnableDrag(DependencyObject element)
{
return (bool)element.GetValue(EnableDragProperty);
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我们添加此附加属性,用户可以通过单击特定元素来拖动整个窗口:
<Border local:EnableDragHelper.EnableDrag="True">
<TextBlock Text="Click me to drag this entire window"/>
</Border>
Run Code Online (Sandbox Code Playgroud)
在DevExpress 的这个示例中,我们将停靠窗口的标题栏替换为我们自己的灰色矩形,然后确保如果用户单击并拖动所述灰色矩形,窗口将正常拖动:
<dx:DXWindow x:Class="DXApplication1.MainWindow" Title="MainWindow" Height="464" Width="765"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
xmlns:local="clr-namespace:DXApplication1.AttachedProperty"
xmlns:dxdove="http://schemas.devexpress.com/winfx/2008/xaml/docking/visualelements"
xmlns:themeKeys="http://schemas.devexpress.com/winfx/2008/xaml/docking/themekeys">
<dxdo:DockLayoutManager FloatingMode="Desktop">
<dxdo:DockLayoutManager.FloatGroups>
<dxdo:FloatGroup FloatLocation="0, 0" FloatSize="179,204" MaxHeight="300" MaxWidth="400"
local:TopmostFloatingGroupHelper.IsTopmostFloatingGroup="True"
>
<dxdo:LayoutPanel ShowBorder="True" ShowMaximizeButton="False" ShowCaption="False" ShowCaptionImage="True"
ShowControlBox="True" ShowExpandButton="True" ShowInDocumentSelector="True" Caption="TradePad General"
AllowDock="False" AllowHide="False" AllowDrag="True" AllowClose="False"
>
<Grid Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" MinHeight="15" Background="#FF515151" Margin="0 0 0 0"
local:EnableDragHelper.EnableDrag="True">
<TextBlock Margin="4" Text="General" FontWeight="Bold"/>
</Border>
<TextBlock Margin="5" Grid.Row="1" Text="Hello, world!" />
</Grid>
</dxdo:LayoutPanel>
</dxdo:FloatGroup>
</dxdo:DockLayoutManager.FloatGroups>
</dxdo:DockLayoutManager>
</dx:DXWindow>
Run Code Online (Sandbox Code Playgroud)
免责声明:我不隶属于DevExpress。此技术适用于任何用户元素,包括标准 WPF或Telerik(另一个优秀的 WPF 库提供程序)。