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

Avalonia封裝實現(xiàn)指定組件允許拖動的工具類

 更新時間:2023年03月01日 09:50:29   作者:tokengo  
這篇文章主要為大家詳細介紹了Avalonia如何封裝實現(xiàn)指定組件允許拖動的工具類,文中的示例代碼講解詳細,感興趣的小伙伴快跟隨小編一起來學習學習吧

創(chuàng)建Avalonia的MVVM項目,命名DragDemo ,然后將項目的Nuget包更新到預覽版

    <ItemGroup>
        <PackageReference Include="Avalonia" Version="11.0.0-preview5" />
        <PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview5" />
        <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
        <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview5" />
        <PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview5" />
        <PackageReference Include="XamlNameReferenceGenerator" Version="1.5.1" />
    </ItemGroup>

更新完成以后ViewLocatorApp.axaml會報錯,

修改ViewLocator.cs為下面的代碼

using System;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using DragDemo.ViewModels;

namespace DragDemo;

public class ViewLocator : IDataTemplate
{
    /// <summary>
    /// 將IControl修改成Control
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public Control Build(object data)
    {
        var name = data.GetType().FullName!.Replace("ViewModel", "View");
        var type = Type.GetType(name);

        if (type != null)
        {
            return (Control)Activator.CreateInstance(type)!;
        }

        return new TextBlock { Text = "Not Found: " + name };
    }

    public bool Match(object data)
    {
        return data is ViewModelBase;
    }
}

添加Avalonia.Themes.Fluent,因為預覽版本的包已經(jīng)獨立需要單獨安裝

<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-preview5" />

打開App.axaml文件,修改為以下代碼

<Application xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="using:DragDemo"
             RequestedThemeVariant="Light" 
             x:Class="DragDemo.App">
    <Application.DataTemplates>
        <local:ViewLocator/>
    </Application.DataTemplates>

    <Application.Styles>
        <FluentTheme DensityStyle="Compact"/>
    </Application.Styles>
    
</Application>

打開Views/MainWindow.axaml

在頭部添加以下代碼,讓窗口無邊框,設(shè)置指定窗口Height="38" Width="471",參數(shù)讓其不要占用整個屏幕,

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:DragDemo.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="DragDemo.Views.MainWindow"
        Icon="/Assets/avalonia-logo.ico"
        ExtendClientAreaToDecorationsHint="True"
        ExtendClientAreaChromeHints="NoChrome"
        ExtendClientAreaTitleBarHeightHint="-1"
        MaxHeight="38" MaxWidth="471"
        Title="DragDemo">
    <Window.Styles>
        <Style Selector="Window">
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Padding" Value="0"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
        </Style>
    </Window.Styles>
    <Design.DataContext>
        <vm:MainWindowViewModel/>
    </Design.DataContext>
    
    <StackPanel>
        <StackPanel Opacity="0.1" Height="38" Width="471">
        </StackPanel>
        <Border Name="Border" Width="471" CornerRadius="10" Opacity="1" Background="#FFFFFF">
            <Button>按鈕</Button>    
        </Border>
    </StackPanel>
</Window>

以下代碼在上面窗口用于設(shè)置窗口無邊框

    <Window.Styles>
        <Style Selector="Window">
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Padding" Value="0"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
        </Style>
    </Window.Styles>

然后打開/Views/MainWindow.axaml.cs文件,將邊框設(shè)置成無邊框,并且設(shè)置窗體透明為WindowTransparencyLevel.Transparent

using Avalonia;
using Avalonia.Controls;

namespace DragDemo.Views;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.TransparencyLevelHint = WindowTransparencyLevel.Transparent;
        ExtendClientAreaToDecorationsHint = true;
        WindowState = WindowState.Maximized;
    }
}

效果圖如下,因為限制了窗體最大大小,并且在按鈕上面添加了透明區(qū)塊,這樣看起來就像是懸浮了

然后我們開始寫指定組件拖動工具類,創(chuàng)建DragControlHelper.cs 以下就是封裝的工具類 定義了一個ConcurrentDictionary靜態(tài)參數(shù),指定組件為Key ,ValueDragModule ,DragModule模型中定義了拖動的邏輯在調(diào)用StartDrag的時候傳遞需要拖動的組件,他會創(chuàng)建一個DragModule對象,創(chuàng)建的時候會創(chuàng)建定時器,當鼠標被按下時啟動定時器,當鼠標被釋放時定時器被停止,定時器用于平滑更新窗體移動,如果直接移動窗體會抖動。

using System;
using System.Collections.Concurrent;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Threading;
using Avalonia.VisualTree;

namespace DragDemo;


public class DragControlHelper
{
    private static ConcurrentDictionary<Control, DragModule> _dragModules = new();

    public static void StartDrag(Control userControl)
    {
        _dragModules.TryAdd(userControl, new DragModule(userControl));
    }

    public static void StopDrag(Control userControl)
    {
        if (_dragModules.TryRemove(userControl, out var dragModule))
        {
            dragModule.Dispose();
        }
    }
}

class DragModule : IDisposable
{
    /// <summary>
    /// 記錄上一次鼠標位置
    /// </summary>
    private Point? lastMousePosition;

    /// <summary>
    /// 用于平滑更新坐標的計時器
    /// </summary>
    private DispatcherTimer _timer;

    /// <summary>
    /// 標記是否先啟動了拖動
    /// </summary>
    private bool isDragging = false;

    /// <summary>
    /// 需要更新的坐標點
    /// </summary>
    private PixelPoint? _targetPosition;

    public Control UserControl { get; set; }

    public DragModule(Control userControl)
    {
        UserControl = userControl;
        // 添加當前控件的事件監(jiān)聽
        UserControl.PointerPressed += OnPointerPressed;
        UserControl.PointerMoved += OnPointerMoved;
        UserControl.PointerReleased += OnPointerReleased;

        // 初始化計時器
        _timer = new DispatcherTimer
        {
            Interval = TimeSpan.FromMilliseconds(10)
        };
        _timer.Tick += OnTimerTick;
    }


    /// <summary>
    /// 計時器事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnTimerTick(object sender, EventArgs e)
    {
        var window = UserControl.FindAncestorOfType<Window>();
        if (window != null && window.Position != _targetPosition)
        {
            // 更新坐標
            window.Position = (PixelPoint)_targetPosition;
        }
    }

    private void OnPointerPressed(object sender, PointerPressedEventArgs e)
    {
        if (!e.GetCurrentPoint(UserControl).Properties.IsLeftButtonPressed) return;
        // 啟動拖動
        isDragging = true;
        // 記錄當前坐標
        lastMousePosition = e.GetPosition(UserControl);
        e.Handled = true;
        // 啟動計時器
        _timer.Start();
    }

    private void OnPointerReleased(object sender, PointerReleasedEventArgs e)
    {
        if (!isDragging) return;
        // 停止拖動
        isDragging = false;
        e.Handled = true;
        // 停止計時器
        _timer.Stop();
    }

    private void OnPointerMoved(object sender, PointerEventArgs e)
    {
        if (!e.GetCurrentPoint(UserControl).Properties.IsLeftButtonPressed) return;

        // 如果沒有啟動拖動,則不執(zhí)行
        if (!isDragging) return;

        var currentMousePosition = e.GetPosition(UserControl);
        var offset =currentMousePosition - lastMousePosition.Value;
        var window = UserControl.FindAncestorOfType<Window>();
        if (window != null)
        {
            // 記錄當前坐標
            _targetPosition = new PixelPoint(window.Position.X + (int)offset.X,
                window.Position.Y + (int)offset.Y);
        }
    }

    public void Dispose()
    {
        _timer.Stop();
        _targetPosition = null;
        lastMousePosition = null;
    }
}

打開MainWindow.axaml.cs,修改成以下代碼 ,在渲染成功以后拿到Border(需要移動的組件),添加到DragControlHelper.StartDrag(border);中,然后再OnUnloaded的時候?qū)?code>Border再卸載掉

using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Threading;

namespace DragDemo.Views;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.TransparencyLevelHint = WindowTransparencyLevel.Transparent;
        ExtendClientAreaToDecorationsHint = true;
        WindowState = WindowState.Maximized;
    }

    public override void Render(DrawingContext context)
    {
        base.Render(context);
        Dispatcher.UIThread.Post(() =>
        {
            var border = this.Find<Border>("Border");
            DragControlHelper.StartDrag(border);
        });
    }

    protected override void OnUnloaded()
    {
        var border = this.Find<Border>("Border");
        DragControlHelper.StopDrag(border);
        base.OnUnloaded();
    }
}

效果展示:

到此這篇關(guān)于Avalonia封裝實現(xiàn)指定組件允許拖動的工具類的文章就介紹到這了,更多相關(guān)Avalonia拖動指定組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于Unity中RectTransform與transform的區(qū)別

    關(guān)于Unity中RectTransform與transform的區(qū)別

    這篇文章主要介紹了Unity中RectTransform與transform的區(qū)別,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • c#固定長度的隨機字符串例子

    c#固定長度的隨機字符串例子

    c#固定長度的隨機字符串例子,需要的朋友可以參考一下
    2013-04-04
  • C#使用Microsoft消息隊列(MSMQ)的示例詳解

    C#使用Microsoft消息隊列(MSMQ)的示例詳解

    Microsoft?Message?Queuing?(MSMQ)?是在多個不同的應(yīng)用之間實現(xiàn)相互通信的一種異步傳輸模式,本文主要介紹了C#如何使用Microsoft消息隊列,需要的可以了解下
    2024-01-01
  • js驗證電話號碼手機號碼的正則表達式

    js驗證電話號碼手機號碼的正則表達式

    本篇文章主要是對js驗證電話號碼手機號碼的正則表達式進行了介紹。需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01
  • C#獲取文件MD5值的實現(xiàn)示例

    C#獲取文件MD5值的實現(xiàn)示例

    文件的md5值,即文件簽名,為了驗證文件的正確性,是否被惡意篡改等。每個文件有一個唯一的md5。下面這篇文中就給大家介紹了如何利用C#獲取文件MD5值,有需要的朋友們可以參考借鑒,下面來一起看看吧。
    2016-12-12
  • C# 鍵值對數(shù)據(jù)排序代碼

    C# 鍵值對數(shù)據(jù)排序代碼

    這篇文章介紹了C# 鍵值對數(shù)據(jù)排序代碼,有需要的朋友可以參考一下
    2013-11-11
  • C#網(wǎng)頁跳轉(zhuǎn)方法總結(jié)

    C#網(wǎng)頁跳轉(zhuǎn)方法總結(jié)

    這篇文章主要介紹了C#網(wǎng)頁跳轉(zhuǎn)方法總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • C# PropertyGrid使用案例詳解

    C# PropertyGrid使用案例詳解

    這篇文章主要介紹了C# PropertyGrid使用案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • c#中Invoke與BeginInvoke的用法及說明

    c#中Invoke與BeginInvoke的用法及說明

    這篇文章主要介紹了c#中Invoke與BeginInvoke的用法及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • C#簡易圖片格式轉(zhuǎn)換器實現(xiàn)方法

    C#簡易圖片格式轉(zhuǎn)換器實現(xiàn)方法

    這篇文章主要介紹了C#簡易圖片格式轉(zhuǎn)換器實現(xiàn)方法,涉及C#基于WinForm操作圖片的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11

最新評論