返回顶部
首页 > 资讯 > 精选 >Avalonia如何封装实现指定组件允许拖动的工具类
  • 499
分享到

Avalonia如何封装实现指定组件允许拖动的工具类

2023-07-05 07:07:27 499人浏览 薄情痞子
摘要

今天小编给大家分享一下Avalonia如何封装实现指定组件允许拖动的工具类的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。创建

今天小编给大家分享一下Avalonia如何封装实现指定组件允许拖动的工具类的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

创建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,因为预览版本的包已经独立需要单独安装

<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

在头部添加以下代码,让窗口无边框,设置指定窗口Height="38" Width="471",参数让其不要占用整个屏幕,

<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>

以下代码在上面窗口用于设置窗口无边框

    <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文件,将边框设置成无边框,并且设置窗体透明为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;    }}

效果图如下,因为限制了窗体最大大小,并且在按钮上面添加了透明区块,这样看起来就像是悬浮了

然后我们开始写指定组件拖动工具类,创建DraGControlHelper.cs 以下就是封装的工具类 定义了一个ConcurrentDictionary静态参数,指定组件为Key ,ValueDragModule ,DragModule模型中定义了拖动的逻辑在调用StartDrag的时候传递需要拖动的组件,他会创建一个DragModule对象,创建的时候会创建定时器,当鼠标被按下时启动定时器,当鼠标被释放时定时器被停止,定时器用于平滑更新窗体移动,如果直接移动窗体会抖动。

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;        // 添加当前控件的事件监听        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;        // 如果没有启动拖动,则不执行        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的时候将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();    }}

效果展示:

Avalonia如何封装实现指定组件允许拖动的工具类

以上就是“Avalonia如何封装实现指定组件允许拖动的工具类”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网精选频道。

--结束END--

本文标题: Avalonia如何封装实现指定组件允许拖动的工具类

本文链接: https://lsjlt.com/news/350368.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Avalonia封装实现指定组件允许拖动的工具类
    创建Avalonia的MVVM项目,命名DragDemo ,然后将项目的Nuget包更新到预览版 <ItemGroup> <Pac...
    99+
    2023-03-01
    Avalonia拖动指定组件工具类 Avalonia拖动指定组件 Avalonia拖动组件
  • Avalonia如何封装实现指定组件允许拖动的工具类
    今天小编给大家分享一下Avalonia如何封装实现指定组件允许拖动的工具类的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。创建...
    99+
    2023-07-05
  • 如何进行基于el-table封装的可拖拽行列、选择列组件的实现
    本篇文章为大家展示了如何进行基于el-table封装的可拖拽行列、选择列组件的实现,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。效果需要环境vue elementUI 拖拽插件Sortable.js...
    99+
    2023-06-22
  • Java如何实现properties文件动态修改并自动保存工具类
    这篇文章主要为大家展示了“Java如何实现properties文件动态修改并自动保存工具类”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java如何实现properties文件动态修改并自动保存...
    99+
    2023-05-30
    java properties
  • 微信小程序如何实现自定义组件封装及父子间组件传值
    小编给大家分享一下微信小程序如何实现自定义组件封装及父子间组件传值,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!首先在我们可以直...
    99+
    2024-04-02
  • 如何实现Vuejs页面的区域化与组件封装
    这篇文章主要介绍如何实现Vuejs页面的区域化与组件封装,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!组件的好处当我用vue写页面的时候,大量的数据页面渲染,引入组件简化主页面的代码...
    99+
    2024-04-02
  • Angular指令如何封装jQuery日期时间插件datetimepicker实现双向绑定
    这篇文章给大家分享的是有关Angular指令如何封装jQuery日期时间插件datetimepicker实现双向绑定的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。00.混乱的前端...
    99+
    2024-04-02
  • vue2如何实现directive自定义指令的封装与全局注册
    本文小编为大家详细介绍“vue2如何实现directive自定义指令的封装与全局注册”,内容详细,步骤清晰,细节处理妥当,希望这篇“vue2如何实现directive自定义指令的封装与全局注册”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢...
    99+
    2023-07-05
  • 基于CSS如何实现MaterialUI按钮点击动画并封装成React组件
    这篇文章主要介绍基于CSS如何实现MaterialUI按钮点击动画并封装成React组件,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!正文首先我们看一下materialUI的按钮点击效果:本质上也是用了css3动画的...
    99+
    2023-06-25
  • Android如何实现自定义组件跟随自己手指主动画圆
    小编给大家分享一下Android如何实现自定义组件跟随自己手指主动画圆,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!具体内容如下首先自己定义一个View子类:package com.example.android...
    99+
    2023-05-30
    android
  • 如何实现yum指定安装某个源下的软件
    本篇内容主要讲解“如何实现yum指定安装某个源下的软件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何实现yum指定安装某个源下的软件”吧!一条命令一个参数搞定代码如下:[root@aikai...
    99+
    2023-06-10
  • C#如何实现文件筛选读取并翻译的自动化工具
    这篇文章主要介绍了C#如何实现文件筛选读取并翻译的自动化工具的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C#如何实现文件筛选读取并翻译的自动化工具文章都会有所收获,下面我们一起来看看吧。思路首选读取项目文件夹...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作