欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#?wpf實(shí)現(xiàn)任意控件更多拖動(dòng)功能

 更新時(shí)間:2023年11月08日 08:38:45   作者:CodeOfCC  
這篇文章主要為大家詳細(xì)介紹了C#?wpf如何實(shí)現(xiàn)任意控件(包括窗口)更多拖動(dòng)功能,文中的示例代碼講解詳細(xì),有興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

前言

上一章我們已經(jīng)實(shí)現(xiàn)了任意控件統(tǒng)一的拖動(dòng)功能,以及能夠方便的給任意控件添加拖動(dòng)了。開發(fā)過程中發(fā)現(xiàn)還是有些功能可以繼續(xù)拓展的,比如cs代碼中移動(dòng)控件、響應(yīng)事件后觸發(fā)拖動(dòng)、限制拖動(dòng)范圍等功能。

一、添加的功能

第五章基礎(chǔ)上添加了如下功能。

1、任意控件MoveTo

這個(gè)功能相對(duì)簡(jiǎn)單,對(duì)不同類型的容器進(jìn)行判斷區(qū)分不同的移動(dòng)邏輯即可。

代碼示例如下:

/// <summary>
/// 任意控件移動(dòng)到指定坐標(biāo)點(diǎn)
/// </summary>
/// <param name="elememt">this</param>
/// <param name="parentPoint">父容器的坐標(biāo)點(diǎn),之所以采樣容器的坐標(biāo)是因?yàn)?,采樣自身坐?biāo)控件位置改變后就會(huì)無效,采樣屏幕坐標(biāo)則需要自己換算dpi(PointToScreen不會(huì)做dpi換算)</param>
public static void MoveTo(this FrameworkElement elememt, Point parentPoint)
{
    var parent = VisualTreeHelper.GetParent(elememt);
    if (parent is Canvas)
    {
        //Canvas移動(dòng)邏輯
    }
    else if (elememt is Window)
    {
        //Window移動(dòng)邏輯
    }
    else
    {
        //Grid或Transform移動(dòng)邏輯,兩種都能適用任意控件
    }
}

在拓展一個(gè)獲取位置的方法,方便MoveTo使用

/// <summary>
/// 獲取控件坐標(biāo),基于父控件。Window則是桌面位置。
/// </summary>
/// <param name="elememt"></param>
public static Point GetPosition(this FrameworkElement elememt)
{
    var parent = VisualTreeHelper.GetParent(elememt);
    if (elememt is Window)
    {
        var window = elememt as Window;
        return new Point(window!.Left, window.Top);
    }
    return elememt.TranslatePoint(new Point(0, 0), parent as UIElement);
}

2、任意控件DragMove

我們知道wpf的Window有DragMove功能,在鼠標(biāo)左鍵按下事件中調(diào)用此方法就能實(shí)現(xiàn)拖動(dòng)功能很方便。任意控件的DragMove也是可以實(shí)現(xiàn)的,我們需要使用第五章的DragMoveable對(duì)象結(jié)合手動(dòng)觸發(fā)事件來實(shí)現(xiàn)。

代碼示例如下:

/// <summary>
/// 點(diǎn)擊拖動(dòng)
/// 與Window的DragMove類似,必須鼠標(biāo)左鍵按下調(diào)用此方法。
/// await 可以等待拖動(dòng)結(jié)束
/// </summary>
/// <param name="elememt">this</param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public static Task DragMove(this FrameworkElement elememt)
{
    if (Mouse.LeftButton != MouseButtonState.Pressed)
    {
        throw new InvalidOperationException("Left button down to call this method");
    }
    var tcs = new TaskCompletionSource();
     //初始化DragMoveable對(duì)象
     //手動(dòng)觸發(fā)elememt的鼠標(biāo)左鍵按下事件
     //拖動(dòng)完成后tcs.SetResult();    
    return tcs.Task;
}

3、邊界限制

添加一個(gè)IsMoveInBounds附加屬性,表示拖動(dòng)范圍是否在父控件內(nèi)。

代碼示例如下:

 public static bool GetIsMoveInBounds(DependencyObject obj)
 {
     return (bool)obj.GetValue(IsMoveInBoundsProperty);
 }

 public static void SetIsMoveInBounds(DependencyObject obj, bool value)
 {
     obj.SetValue(IsMoveInBoundsProperty, value);
 }
 /// <summary>
 /// 是否在父容器區(qū)域內(nèi)拖動(dòng),不會(huì)超出邊界
 /// </summary>
 // Using a DependencyProperty as the backing store for IsMoveInBounds.  This enables animation, styling, binding, etc...
 public static readonly DependencyProperty IsMoveInBoundsProperty =
     DependencyProperty.RegisterAttached("IsMoveInBounds", typeof(bool), typeof(Move), new PropertyMetadata(true));

第五章 附加屬性實(shí)現(xiàn)任意拖動(dòng)的拖動(dòng)邏輯中添加相應(yīng)的限制功能,比如Canvas的示例如下:

var p = _parent as Canvas;
if (GetIsMoveInBounds(c))
//修正移動(dòng)范圍
{
    if (left < 0) left = 0;
    if (top < 0) top = 0;
    if (left + c.ActualWidth > p.ActualWidth) left = p.ActualWidth - c.ActualWidth;
    if (top + c.ActualHeight > p.ActualHeight) top = p.ActualHeight - c.ActualHeight;
}                     

4、窗口最大化拖動(dòng)還原

Windows系統(tǒng)的窗口最大化拖動(dòng)標(biāo)題時(shí)會(huì)自動(dòng)恢復(fù)為普通狀態(tài)的窗口,實(shí)現(xiàn)無邊框窗口后則失去了這個(gè)功能,需要自己實(shí)現(xiàn),而且恢復(fù)普通狀態(tài)的窗口的位置還有一定的邏輯。

代碼示例如下:

if (window.WindowState == WindowState.Maximized)
//最大化時(shí)拖動(dòng)邏輯
{   
    //恢復(fù)為普通窗口
    window.WindowState = WindowState.Normal;
    double width = SystemParameters.PrimaryScreenWidth;//得到屏幕整體寬度
    double height = SystemParameters.PrimaryScreenHeight;//得到屏幕整體高度
    //根據(jù)鼠標(biāo)的位置調(diào)整窗口位置,基本邏輯是橫向?yàn)槭髽?biāo)為中點(diǎn),縱向?yàn)槭髽?biāo)頂部,超出屏幕范圍則修正到靠近的那一邊。
}

5、拖動(dòng)事件

提供3個(gè)拖動(dòng)事件,拖動(dòng)結(jié)束、拖動(dòng)變化、拖動(dòng)結(jié)束。

代碼示例如下:

 /// <summary>
 ///  拖動(dòng)開始事件
 /// </summary>
 public static readonly RoutedEvent DragMoveStartedEvent = EventManager.RegisterRoutedEvent("DragMoveStarted", RoutingStrategy.Direct, typeof(EventHandler<DragMoveStartedEventArgs>), typeof(Move));
/// <summary>
/// 拖動(dòng)變化事件
/// </summary>
public static readonly RoutedEvent DragMoveDeltaEvent = EventManager.RegisterRoutedEvent("DragMoveDelta", RoutingStrategy.Direct, typeof(EventHandler<DragMoveDeltaEventArgs>), typeof(Move));
/// <summary>
/// 拖動(dòng)結(jié)束事件
/// </summary>
public static readonly RoutedEvent DragMoveCompletedEvent = EventManager.RegisterRoutedEvent("DragMoveCompleted", RoutingStrategy.Direct, typeof(EventHandler<DragMoveCompletedEventArgs>), typeof(Move));

二、使用示例

由于本章是第五章的拓展,基本功能可以參考第五章。

1、MoveTo

xaml

<Window x:Class="WpfMove.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfMove"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        >
    <Grid>
        <Button Width="180" Height="30" Click="Button_Click">Gird中點(diǎn)擊按鈕右移10</Button>
        <StackPanel>
            <Button Width="180" Height="30" Click="Button_Click">StackPanel中點(diǎn)擊按鈕右移10</Button>
        </StackPanel>
        <Canvas>
            <Button Width="180" Height="30" Click="Button_Click">Canvas中點(diǎn)擊按鈕右移10</Button>
        </Canvas>
    </Grid>
</Window>

因?yàn)槭峭卣狗椒ǎ垣@取到控件對(duì)象直接調(diào)用moveTo即可。

cs

using AC;
using System.Windows;
using System.Windows.Media;

namespace WpfMove
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var fe = sender as FrameworkElement;
            //獲取控件的位置
            var p = fe.GetPosition();
            //右偏移10
            p.Offset(10, 0);
            fe.MoveTo(p);
        }
    }
}

效果預(yù)覽

2、DragMove

xaml

<Window x:Class="WpfMove.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfMove"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        >
    <Grid>
        <TextBlock Background="Aqua" TextAlignment="Center" Margin="0,80,0,0" Width="180" Height="30"  MouseDown="TextBlock_MouseDown" >Gird中點(diǎn)擊拖動(dòng)</TextBlock>
        <StackPanel>
            <TextBlock Background="Aqua" TextAlignment="Center" Margin="0,80,0,0" Width="180" Height="30"  MouseDown="TextBlock_MouseDown" >StackPanel中點(diǎn)擊拖動(dòng)</TextBlock>
        </StackPanel>
        <Canvas >
            <TextBlock Background="Aqua" TextAlignment="Center" Margin="0,80,0,0" Width="180" Height="30"  MouseDown="TextBlock_MouseDown" >Canvas中點(diǎn)擊拖動(dòng)</TextBlock>
        </Canvas>
    </Grid>
</Window>

此方法也是拓展方法,在鼠標(biāo)按下事件中任意控件都可以調(diào)用此方法,可以通過await等待拖動(dòng)完成。

cs

using AC;
using System;
using System.Windows;

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

        private async void TextBlock_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var fe = sender as FrameworkElement;
            await fe.DragMove();
            Console.WriteLine("拖動(dòng)完成");
        }
    }
}

效果預(yù)覽

3、邊界限制

通過附加屬性IsMoveInBounds設(shè)置是否限制邊界,默認(rèn)為false。

xaml

<Window x:Class="WpfMove.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfMove"
         xmlns:ac="clr-namespace:AC"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        >
    <Grid>
        <TextBlock HorizontalAlignment="Left" Background="Aqua" TextAlignment="Center" Margin="0,80,0,0" Width="180" Height="60"  ac:Move.IsDragMoveable="True" ac:Move.IsMoveInBounds="True">拖動(dòng)限制邊界</TextBlock>
        <TextBlock HorizontalAlignment="Right" Background="Aqua" TextAlignment="Center" Margin="0,80,0,0" Width="180" Height="60" ac:Move.IsDragMoveable="True" ac:Move.IsMoveInBounds="False">拖動(dòng)不限制邊界</TextBlock>
    </Grid>
</Window>

效果預(yù)覽

4、窗口最大化拖動(dòng)還原

內(nèi)部實(shí)現(xiàn)已支持最大化拖動(dòng)還原,只需要設(shè)置窗口可拖動(dòng)即可,使用場(chǎng)景是無邊框窗口自定義標(biāo)題欄。

xaml

<Window x:Class="WpfMove.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfMove"
        xmlns:ac="clr-namespace:AC"
        mc:Ignorable="d"
        WindowStyle="None"
        ResizeMode="NoResize"
        WindowState="Normal"
        Title="MainWindow" Height="450" Width="800"
        x:Name="window"
        >
    <Grid>
        <Border VerticalAlignment="Top" Height="40" Background="#333333" ac:Move.DragMoveTarget="{Binding ElementName= window}"  MouseLeftButtonDown="Border_MouseLeftButtonDown">
            <TextBlock Margin="0,0,10,0" VerticalAlignment="Center" HorizontalAlignment="Right"  Foreground="White" Text="標(biāo)題欄拖動(dòng)窗口"></TextBlock>
        </Border>
    </Grid>
</Window>

cs

using System.Windows;
namespace WpfMove
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Border_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2) WindowState = WindowState != WindowState.Maximized ? WindowState = WindowState.Maximized : WindowState = WindowState.Normal;
        }
    }
}

效果預(yù)覽

5、拖動(dòng)事件

xaml

<Window x:Class="WpfMove.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfMove"
         xmlns:ac="clr-namespace:AC"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        >
    <StackPanel>
        <TextBlock Background="Aqua" 
                   TextAlignment="Center"
                   Margin="0,80,0,0" Width="180" Height="30"  
                   ac:Move.IsDragMoveable="True"   
                   ac:Move.DragMoveStarted="window_DragMoveStarted"
                   ac:Move.DragMoveCompleted="window_DragMoveCompleted"
                   ac:Move.DragMoveDelta="window_DragMoveDelta">StackPanel中點(diǎn)擊拖動(dòng)</TextBlock>
    </StackPanel>
</Window>

cs

using AC;
using System;
using System.Windows;

namespace WpfMove
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void window_DragMoveStarted(object sender, DragMoveStartedEventArgs e)
        {
            Console.WriteLine("拖動(dòng)開始");
        }

        private void window_DragMoveCompleted(object sender, DragMoveCompletedEventArgs e)
        {
            Console.WriteLine("拖動(dòng)完成");
        }

        private void window_DragMoveDelta(object sender, DragMoveDeltaEventArgs e)
        {
            Console.WriteLine("橫向偏移:"+e.HorizontalOffset + "," +"縱向偏移:"+ e.VerticalOffset);
        }
    }
}

效果預(yù)覽

總結(jié)

拓展更多的拖動(dòng)功能后使用變得更加方便了,靈活度也提高了。使用xmal或cs代碼都能實(shí)現(xiàn)拖動(dòng),實(shí)現(xiàn)自定義標(biāo)題欄也變得很簡(jiǎn)單,有了拖動(dòng)事件也可以做一些撤銷重做的功能??偟膩碚f,本文的拖動(dòng)功能一定程度可以作為通用的模塊在項(xiàng)目中使用了。

以上就是C# wpf實(shí)現(xiàn)任意控件更多拖動(dòng)功能的詳細(xì)內(nèi)容,更多關(guān)于C# wpf控件拖動(dòng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#開發(fā)Winform實(shí)現(xiàn)學(xué)生管理系統(tǒng)

    C#開發(fā)Winform實(shí)現(xiàn)學(xué)生管理系統(tǒng)

    這篇文章介紹了C#開發(fā)Winform實(shí)現(xiàn)學(xué)生管理系統(tǒng)的項(xiàng)目案例,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • c#關(guān)于非托管內(nèi)存的釋放問題及解讀

    c#關(guān)于非托管內(nèi)存的釋放問題及解讀

    這篇文章主要介紹了c#關(guān)于非托管內(nèi)存的釋放問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C#如何使用Task執(zhí)行異步操作

    C#如何使用Task執(zhí)行異步操作

    這篇文章主要介紹了C#如何使用Task執(zhí)行異步操作,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-05-05
  • silverlight實(shí)現(xiàn)圖片局部放大效果的方法

    silverlight實(shí)現(xiàn)圖片局部放大效果的方法

    這篇文章主要介紹了silverlight實(shí)現(xiàn)圖片局部放大效果的方法,結(jié)合實(shí)例形式分析了silverlight針對(duì)圖片屬性的相關(guān)操作技巧,需要的朋友可以參考下
    2017-03-03
  • C#實(shí)現(xiàn)三元組的使用示例

    C#實(shí)現(xiàn)三元組的使用示例

    本文介紹了C#中的三元組數(shù)據(jù)結(jié)構(gòu),以及如何使用三元組在C#中進(jìn)行一些特定的計(jì)算,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • C#集合之字典的用法

    C#集合之字典的用法

    這篇文章介紹了C#集合之字典的用法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#一個(gè)方法返回多個(gè)值示例

    C#一個(gè)方法返回多個(gè)值示例

    這篇文章主要介紹了C#一個(gè)方法返回多個(gè)值示例,需要的朋友可以參考下
    2014-02-02
  • 詳解C#中委托,事件與回調(diào)函數(shù)講解

    詳解C#中委托,事件與回調(diào)函數(shù)講解

    這篇文章主要介紹了詳解C#中委托,事件與回調(diào)函數(shù)講解,小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。
    2016-12-12
  • C#后臺(tái)調(diào)用前臺(tái)JS函數(shù)方法

    C#后臺(tái)調(diào)用前臺(tái)JS函數(shù)方法

    今天小編就為大家分享一篇關(guān)于C#后臺(tái)調(diào)用前臺(tái)JS函數(shù)方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • C#使用ScrapySharp實(shí)現(xiàn)多線程下載操作

    C#使用ScrapySharp實(shí)現(xiàn)多線程下載操作

    在現(xiàn)代互聯(lián)網(wǎng)應(yīng)用中,數(shù)據(jù)抓取是一個(gè)常見的需求,無論是為了數(shù)據(jù)分析、內(nèi)容聚合還是自動(dòng)化測(cè)試,ScrapySharp 是一個(gè)基于 .NET 的輕量級(jí)、高性能的網(wǎng)頁抓取庫,本文將探討如何在 C# 中使用 ScrapySharp 實(shí)現(xiàn)多線程下載策略,需要的朋友可以參考下
    2024-08-08

最新評(píng)論