WPF-利用装饰器实现空间的自由拖动

这篇具有很好参考价值的文章主要介绍了WPF-利用装饰器实现空间的自由拖动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  在项目中经常会遇到类似如下要求的需求,创建允许自由拖动的控件,这样的需求可以使用WPF的装饰器Adorner来实现。

WPF-利用装饰器实现空间的自由拖动

 文章来源地址https://www.toymoban.com/news/detail-670701.html

一、什么是装饰器?

装饰器是一种特殊类型的FrameworkElement,装饰器始终呈现在被装饰元素的顶部,用于向用户提供可视化提示。装饰器可以在不改变原有控件结构的基础上,将功能点增加到元素中或元素上提供视觉效果等,如WPF的光标效果,焦点效果等都是通过装饰器来实现的。
装饰器是一个始终位于装饰元素或装饰元素集合顶部的呈现图层,其呈现独立与它所绑定的UIElement,WPF中的装饰器是在一个单独的曾AnornerLayer上进行绘制的,该层位于普通控件元素之上,而且允许多个AdornerLayer进行叠加,当加入AdornerLayer层后,Adorner会默认使用其所装饰元素的左上角作为原点进行定位。
  • Adorner 是一个抽象类,所有装饰器的实现都需要继承此类,比如ThumbBorderAdorner
  • AdornerLayer 一个类,表示一个或多个装饰元素的装饰器呈现层
    • 利用AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(userControl)函数,来获取指定控件是否有装饰器布局层
    • 利用Adorner[] adorners = adornerLayer.GetAdorners(userControl);,来查看当前控件的装饰器个数
  • AdornerDecorator 一个类,为可视化树中的子元素提供AdornerLayer
WPF-利用装饰器实现空间的自由拖动

二、装饰器的使用场景

  • 为现有的元素添加额外的装饰,如为Border添加8个装饰矩形
 

三、如何创建自定义的装饰器?

  • 创建一个类,继承自Adorner类
  • 重写此类中需要的函数
    • OnRender(DrawingContext drawingContext) 在派生类中重写,参与由布局系统控制的呈现操作,调用此方法时,不直接使用此元素的呈现指令,而是将其保留供布局和绘制在以后异步使用,可以使用drawingContext 来绘制各种形状以及图形。
    • ArrangeOverride() 为FrameworkElement派生类定位子元素并确定大小,在其中调用Arrange()函数,来定位子元素
    • GetVisualChild() //获取第几个Thumb控件,在构造时使用
  • 简单的装饰可以重写OnRender()函数,在其中绘制所需要的装饰,参照BorderAdorner
  • 复杂一些的如需要可以定义VisualCollection的集合来存放装饰器,重写ArrangeOverride和GetVisualChild函数来实现,参照ThumbBorderAdorner
 

四、给控件使用自定义的Adorner

  • 添加Adorner
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(userControl);
if (adornerLayer != null)
{
    Adorner[] adorners = adornerLayer.GetAdorners(userControl);
    if (adorners == null || adorners.Count() == 0)
    {
        adornerLayer.Add(new ThumbBorderAdorner(userControl)
        {
            DragCompletedAction = ThumbBorderAdornerDragCompletedActionFunc
        });
    }
}

 

  • 移除 Adorner
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(userControl);
if (adornerLayer != null)
{
    Adorner[] adorners = adornerLayer.GetAdorners(userControl);
    if (adorners != null && adorners.Count() > 0)
        adornerLayer.Remove(adorners[0]);
}

 

五、处理拖拽Thumb时,导致控件范围超出父级容器的情况

  • 即在添加装饰器的控件中添加UserControl_SizeChanged()来处理控件大小和和未知变化
private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
{
    int tempMargin = 1;  //MarkRectUserControl控件始终在父级容器的1个像素以内

    double left = Canvas.GetLeft(this);
    if (left < tempMargin)
    {
        left = tempMargin;
        Canvas.SetLeft(this, left);
    }

    double top = Canvas.GetTop(this);
    if (top < tempMargin)
    {
        top = tempMargin;
        Canvas.SetTop(this, top);
    }

    if (left + this.ActualWidth > canvasParent.ActualWidth - tempMargin)
        this.Width = canvasParent.ActualWidth - tempMargin - left;

    if (top + this.ActualHeight > canvasParent.ActualHeight - tempMargin)
        this.Height = canvasParent.ActualHeight - tempMargin - top;

}

 

六、测试使用

 

<UserControl x:Class="BlogDemo.Views.AdornerTestUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:BlogDemo.Views"
             mc:Ignorable="d" 
             Background="White"
             d:DesignHeight="450" d:DesignWidth="800"
             FontSize="20"
             Foreground="Blue"
             Loaded="UserControl_Loaded"
             >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        
        <TextBlock Text="请拖拽Thumb控件来改变,控件大小。" HorizontalAlignment="Center" Margin="10"/>

        <Canvas x:Name="Canvas_Main" Grid.Row="1">
            <Border x:Name="Border_Text" Canvas.Left="200" Canvas.Top="100" Width="200" Height="100" BorderThickness="2" BorderBrush="Green" SizeChanged="Border_Text_SizeChanged"/>
        </Canvas>
    </Grid>
</UserControl>
/// <summary>
/// AdornerTestUserControl.xaml 的交互逻辑
/// </summary>
public partial class AdornerTestUserControl : UserControl
{
    public AdornerTestUserControl()
    {
        InitializeComponent();
    }

    private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
        AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(Border_Text);
        if (adornerLayer != null)
        {
            Adorner[] adorners = adornerLayer.GetAdorners(Border_Text);
            if (adorners == null || adorners.Count() == 0)
            {
                adornerLayer.Add(new ThumbBorderAdorner(Border_Text));
            }
        }
    }

    private void Border_Text_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        int tempMargin = 100; 

        double left = Canvas.GetLeft(Border_Text);
        if (left < tempMargin)
        {
            left = tempMargin;
            Canvas.SetLeft(Border_Text, left);
        }

        double top = Canvas.GetTop(Border_Text);
        if (top < tempMargin)
        {
            top = tempMargin;
            Canvas.SetTop(Border_Text, top);
        }

        if (Border_Text.ActualWidth < tempMargin)
            Border_Text.Width = tempMargin;

        if (Border_Text.ActualHeight < tempMargin)
            Border_Text.Height = tempMargin;

        if (left + Border_Text.ActualWidth > Canvas_Main.ActualWidth - tempMargin)
            Border_Text.Width = Canvas_Main.ActualWidth - tempMargin - left;

        if (top + Border_Text.ActualHeight > Canvas_Main.ActualHeight - tempMargin)
            Border_Text.Height = Canvas_Main.ActualHeight - tempMargin - top;
    }
}

 

 

源码地址:https://gitee.com/LiuShuiRuoBing/code_blog

 

 

到了这里,关于WPF-利用装饰器实现空间的自由拖动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 在WPF应用中使用GongSolutions.WPF.DragDrop实现列表集合控件的拖动处理

    WPF应用中,控件本身也可以通过实现事件代码实现拖动的处理,不过如果我们使用GongSolutions.WPF.DragDrop来处理,事情会变得更加简单轻松,它支持很多控件的拖动处理,如ListBox, ListView, TreeView, DataGrid等源自ItemsControl的控件,本篇随笔介绍在工作流模块中拖动TreeView和DataGrid列表

    2024年02月05日
    浏览(42)
  • 利用colab实现AI绘画自由

    最近AIGC真的很火,除了chatGPT外,AI绘画也是热度不减。最近也是决定抽空上手尝试一下,但奈何我的本本太渣,丐版Mac跑跑数据还行,跑Stable Diffusion根本没戏。所以还是决定白嫖谷歌的colab。 网上关于本地部署的教程很多,最火的例如b站的秋葉大神,mac版的也不少,可自行

    2024年02月09日
    浏览(43)
  • Android:RecyclerView自由拖动item

    原生就自带有可拖动item的工具:ItemTouchHelper 看下效果: 可拖动RecyclerView预览效果 接下来我们看如何使用。 其中判断条件中的item.isMovable这边是记录该item是否可以拖动,也可以换成其他判断条件比如根据位置判断等。 另外,需要留意一点,如果你是在onBindViewHolder中有设置点

    2024年01月23日
    浏览(47)
  • Mkdocs中利用Js实现大小圈鼠标拖动样式

    在 docs/javascripts/extra.js 下复制粘贴: 其中比较重要的参数就是鼠标的尺寸和颜色,已经在上图中标出,目前发现颜色只支持RGB写法和固有名称写法(例如red这种),其他参数也可以自行摸索: 在docs/stylesheets/extra.css添加如下代码: 这里比较重要的参数就是鼠标跟随的圆形颜

    2024年02月15日
    浏览(37)
  • C#在winForm窗体中添加一个可以自由拖动的控件

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 目录 文章目录 一、实现步骤 1.创建一个新的Windows窗体项目 2.添加控件如图 3.代码部分 总结 textBox1=鼠标在需要拖动的控件中的坐标 X 值 textBox2=鼠标在需要拖动的控件中的坐标 Y 值 textBox3=需要

    2024年01月19日
    浏览(44)
  • WPF网格拖动自动布局效果

    使用Canvas和鼠标相关事件实现如下的效果: XAML代码: C#代码 项目地址github

    2024年02月11日
    浏览(31)
  • 浅谈WPF之控件拖拽与拖动

    使用过office的visio软件画图的小伙伴都知道,画图软件分为两部分,左侧图形库,存放各种图标,右侧是一个画布,将左侧图形库的图标控件拖拽到右侧画布,就会生成一个新的控件,并且可以自由拖动。那如何在WPF程序中,实现类似的功能呢?今天就以一个简单的小例子,

    2024年02月05日
    浏览(60)
  • flutter web项目中鼠标拖动无法实现滚动效果

    在完成web的flutter项目时,发现ListView列表使用鼠标拖动无法滚动,尝试发现使用触摸板可以实现滚动,但如果用户使用没有触摸板的电脑或列表为横向滚动时就无法实现项目需求了,在解决问题的过程中尝试了以下方法: 1.尝试使用点击事件模拟滑动手势 如果web项目中无法使

    2024年02月09日
    浏览(44)
  • C# wpf利用Clip属性实现截屏框

    第一章 使用GDI+实现截屏 第二章 制作截屏框(本章) ______第一节 使用DockPanel制作截屏框 ______第二节 利用Clip属性实现截屏框(本节) 第三章 实现截屏框热键截屏 第四章 实现截屏框实时截屏 第五章 使用ffmpeg命令行实现录屏 第一节已经实现过截屏框,实现方法相对简单,也仅

    2024年01月23日
    浏览(42)
  • 【无人机】采用最基本的自由空间路损模型并且不考虑小尺度衰落(多径多普勒)固定翼无人机轨迹规划(Matlab代码实现)

    💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 2.1 文献结果:  2.2 Matlab代码复现结果 🎉

    2024年02月01日
    浏览(65)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包