我需要窗口內的某個元素擁有拖動整個窗口的功能,也就是這個元素在拖動的時候是拖動整個窗口。而且我還開出一個有趣的方法,這個作爲窗口的拖拽的元素如果是用戶在元素上拖動,那麼將會拖動窗口,如果用戶是點擊,將會觸發點擊事件
附加屬性可以給某個元素附加有趣的功能,本文的功能需要拖動元素的時候實際上是拖動窗口,第二個是元素是支持點擊的
拖動窗口使用的是窗口的 DragMove 方法
元素支持點擊用的是 WPF 給任意控件通過按下移動擡起封裝點擊事件 方法
因此本文需要引入 WPF 給任意控件通過按下移動擡起封裝點擊事件 的 InputHelper 類作爲輔助
用法如下,寫一個簡單的界面,放一個元素作爲拖動的元素
<Border x:Name="DraggingElement" Width="100" Height="100" Background="Gray">
<TextBlock x:Name="TextBlock" Margin="10,10,10,10" HorizontalAlignment="Center"></TextBlock>
</Border>
上面代碼的 DraggingElement 就是用來拖動窗口的元素
接下來在元素放一個 WindowDraggingExtension.DragWindow 附加屬性
<Border x:Name="DraggingElement" Width="100" Height="100" Background="Gray">
<framework:WindowDraggingExtension.DragWindow>
<framework:WindowDraggingExtension />
</framework:WindowDraggingExtension.DragWindow>
<TextBlock x:Name="TextBlock" Margin="10,10,10,10" HorizontalAlignment="Center"></TextBlock>
</Border>
注意 framework:
是我的命名空間,請按照自己的代碼修改爲你的命名空間
此時嘗試運行代碼,拖動一下 DraggingElement 這個元素,可以看到拖動的是窗口。這個方法支持觸摸拖動
這個附加屬性能做到的功能類似 QQ 寵物,可以拖動,可以點擊提示更多內容
本文用到的這個附加屬性代碼如下
/// <summary>
/// 窗口拖拽的附加方法
/// </summary>
public class WindowDraggingExtension
{
/// <summary>
/// 表示元素作爲附加某個窗口提供拖拽的功能
/// </summary>
public static readonly DependencyProperty DragWindowProperty = DependencyProperty.RegisterAttached(
"DragWindow", typeof(WindowDraggingExtension), typeof(WindowDraggingExtension),
new PropertyMetadata(default(WindowDraggingExtension),
new PropertyChangedCallback(OnDragWindowPropertyChanged)));
private static void OnDragWindowPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// 僅有設置,不會存在多次設置,也沒有反過來
if (e.NewValue is WindowDraggingExtension windowDragging && d is UIElement element)
{
InputHelper.AttachMouseDownMoveUpToClick(element,
delegate { windowDragging.DraggingElementClicked?.Invoke(null, EventArgs.Empty); }, delegate
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
var targetWindow = windowDragging.TargetWindow
?? Window.GetWindow(element);
targetWindow?.DragMove();
}
});
}
}
/// <summary>
/// 設置元素作爲窗口的拖拽元素
/// </summary>
/// <param name="element"></param>
/// <param name="value"></param>
public static void SetDragWindow(DependencyObject element, WindowDraggingExtension value)
{
element.SetValue(DragWindowProperty, value);
}
/// <summary>
/// 獲取元素作爲窗口拖拽屬性
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
public static WindowDraggingExtension GetDragWindow(DependencyObject element)
{
return (WindowDraggingExtension) element.GetValue(DragWindowProperty);
}
/// <summary>
/// 附加的拖動的窗口,提供此屬性僅僅是爲了提升性能,可以不設置。如不設置將使用 Window.GetWindow 方法獲取當前元素所在窗口
/// </summary>
public Window TargetWindow { set; get; }
/// <summary>
/// 拖動的元素實際是被點擊時觸發
/// </summary>
public event EventHandler DraggingElementClicked;
}
上面代碼 InputHelper 需要從 WPF 給任意控件通過按下移動擡起封裝點擊事件 複製
通過閱讀上面代碼,可以看到還有兩個可以設置的屬性,一個是 TargetWindow 屬性,一個是元素被點擊的事件
設置 TargetWindow 屬性主要是爲了提升一點性能,通過 TargetWindow 獲取窗口,而不需要通過 Window.GetWindow 方法獲取當前元素所在窗口,使用方法如下
<Window x:Name="CurrentWindow" 忽略元素>
<Border x:Name="DraggingElement" Width="100" Height="100" Background="Gray">
<framework:WindowDraggingExtension.DragWindow>
<framework:WindowDraggingExtension TargetWindow="{x:Reference CurrentWindow}" DraggingElementClicked="WindowDraggingExtension_OnDraggingElementClicked"/>
</framework:WindowDraggingExtension.DragWindow>
<TextBlock x:Name="TextBlock" Margin="10,10,10,10" HorizontalAlignment="Center"></TextBlock>
</Border>
</Window>
上面代碼還使用方法拿到元素點擊的事件,後臺代碼如下
private void WindowDraggingExtension_OnDraggingElementClicked(object sender, EventArgs e)
{
TextBlock.Text = "林德熙是逗比";
}
我搭建了自己的博客 https://blog.lindexi.com/ 歡迎大家訪問,裏面有很多新的博客。只有在我看到博客寫成熟之後纔會放在csdn或博客園,但是一旦發佈了就不再更新
如果在博客看到有任何不懂的,歡迎交流,我搭建了 dotnet 職業技術學院 歡迎大家加入
如有不方便在博客評論的問題,可以加我 QQ 2844808902 交流
本作品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名林德熙(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我聯繫。