WPF实现一个带旋转动画的菜单栏

WPF实现一个带旋转动画的菜单栏

  • 一、创建WPF项目及文件
    • 1、创建项目
    • 2、创建文件夹及文件
    • 3、添加引用
  • 二、代码实现
    • 2.ControlAttachProperty类

一、创建WPF项目及文件

1、创建项目

打开VS2022,创建一个WPF项目,如下所示
在这里插入图片描述在这里插入图片描述

2、创建文件夹及文件

创建资源文件夹,添加字体图标文件,添加 Menu样式文件,如下所示
在这里插入图片描述
创建公共附加属性用控件类库,并创建对应的 ControlAttachProperty 类文件如下:
在这里插入图片描述
在这里插入图片描述

3、添加引用

右键 Menu_WPF 添加引用,将类库引用到当前项目
在这里插入图片描述

二、代码实现

2.ControlAttachProperty类

代码如下(示例):

using Microsoft.Win32;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using CheckBox = System.Windows.Controls.CheckBox;
using ComboBox = System.Windows.Controls.ComboBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using RadioButton = System.Windows.Controls.RadioButton;
using RichTextBox = System.Windows.Controls.RichTextBox;
using TextBox = System.Windows.Controls.TextBox;

namespace Common.UserControl.Extession
{
    /// <summary>
    /// 公共附加属性
    /// </summary>
    public static class ControlAttachProperty
    {

        #region FocusBorderBrush 焦点边框色,输入控件

        public static readonly DependencyProperty FocusBorderBrushProperty = DependencyProperty.RegisterAttached(
            "FocusBorderBrush", typeof(Brush), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null));
        public static void SetFocusBorderBrush(DependencyObject element, Brush value)
        {
            element.SetValue(FocusBorderBrushProperty, value);
        }
        public static Brush GetFocusBorderBrush(DependencyObject element)
        {
            return (Brush)element.GetValue(FocusBorderBrushProperty);
        }

        #endregion

        #region MouseOverBorderBrush 鼠标进入边框色,输入控件

        public static readonly DependencyProperty MouseOverBorderBrushProperty =
            DependencyProperty.RegisterAttached("MouseOverBorderBrush", typeof(Brush), typeof(ControlAttachProperty),
                new FrameworkPropertyMetadata(Brushes.Transparent,
                    FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Inherits));

        /// <summary>
        /// Sets the brush used to draw the mouse over brush.
        /// </summary>
        public static void SetMouseOverBorderBrush(DependencyObject obj, Brush value)
        {
            obj.SetValue(MouseOverBorderBrushProperty, value);
        }

        /// <summary>
        /// Gets the brush used to draw the mouse over brush.
        /// </summary>
        [AttachedPropertyBrowsableForType(typeof(TextBox))]
        [AttachedPropertyBrowsableForType(typeof(CheckBox))]
        [AttachedPropertyBrowsableForType(typeof(RadioButton))]
        [AttachedPropertyBrowsableForType(typeof(DatePicker))]
        [AttachedPropertyBrowsableForType(typeof(ComboBox))]
        [AttachedPropertyBrowsableForType(typeof(RichTextBox))]
        public static Brush GetMouseOverBorderBrush(DependencyObject obj)
        {
            return (Brush)obj.GetValue(MouseOverBorderBrushProperty);
        }

        #endregion

        #region AttachContentProperty 附加组件模板
        /// <summary>
        /// 附加组件模板
        /// </summary>
        public static readonly DependencyProperty AttachContentProperty = DependencyProperty.RegisterAttached(
            "AttachContent", typeof(ControlTemplate), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null));

        public static ControlTemplate GetAttachContent(DependencyObject d)
        {
            return (ControlTemplate)d.GetValue(AttachContentProperty);
        }

        public static void SetAttachContent(DependencyObject obj, ControlTemplate value)
        {
            obj.SetValue(AttachContentProperty, value);
        }
        #endregion

        #region WatermarkProperty 水印
        /// <summary>
        /// 水印
        /// </summary>
        public static readonly DependencyProperty WatermarkProperty = DependencyProperty.RegisterAttached(
            "Watermark", typeof(string), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(""));

        public static string GetWatermark(DependencyObject d)
        {
            return (string)d.GetValue(WatermarkProperty);
        }

        public static void SetWatermark(DependencyObject obj, string value)
        {
            obj.SetValue(WatermarkProperty, value);
        }
        #endregion

        #region FIconProperty 字体图标
        /// <summary>
        /// 字体图标
        /// </summary>
        public static readonly DependencyProperty FIconProperty = DependencyProperty.RegisterAttached(
            "FIcon", typeof(string), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(""));

        public static string GetFIcon(DependencyObject d)
        {
            return (string)d.GetValue(FIconProperty);
        }

        public static void SetFIcon(DependencyObject obj, string value)
        {
            obj.SetValue(FIconProperty, value);
        }
        #endregion

        #region FIconSizeProperty 字体图标大小
        /// <summary>
        /// 字体图标
        /// </summary>

        public static readonly DependencyProperty FIconSizeProperty = DependencyProperty.RegisterAttached(
            "FIconSize", typeof(double), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(12D));

        public static double GetFIconSize(DependencyObject d)
        {
            return (double)d.GetValue(FIconSizeProperty);
        }

        public static void SetFIconSize(DependencyObject obj, double value)
        {
            obj.SetValue(FIconSizeProperty, value);
        }
        #endregion

        #region FIconMarginProperty 字体图标边距
        /// <summary>
        /// 字体图标
        /// </summary>
        public static readonly DependencyProperty FIconMarginProperty = DependencyProperty.RegisterAttached(
            "FIconMargin", typeof(Thickness), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null));

        public static Thickness GetFIconMargin(DependencyObject d)
        {
            return (Thickness)d.GetValue(FIconMarginProperty);
        }

        public static void SetFIconMargin(DependencyObject obj, Thickness value)
        {
            obj.SetValue(FIconMarginProperty, value);
        }
        #endregion

        #region AllowsAnimationProperty 启用旋转动画
        /// <summary>
        /// 启用旋转动画
        /// </summary>
        public static readonly DependencyProperty AllowsAnimationProperty = DependencyProperty.RegisterAttached("AllowsAnimation"
            , typeof(bool), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(false, AllowsAnimationChanged));

        public static bool GetAllowsAnimation(DependencyObject d)
        {
            return (bool)d.GetValue(AllowsAnimationProperty);
        }

        public static void SetAllowsAnimation(DependencyObject obj, bool value)
        {
            obj.SetValue(AllowsAnimationProperty, value);
        }

        /// <summary>
        /// 旋转动画刻度
        /// </summary>
        private static DoubleAnimation RotateAnimation = new DoubleAnimation(0, new Duration(TimeSpan.FromMilliseconds(200)));

        /// <summary>
        /// 绑定动画事件
        /// </summary>
        private static void AllowsAnimationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var uc = d as FrameworkElement;
            if (uc == null) return;
            if (uc.RenderTransformOrigin == new Point(0, 0))
            {
                uc.RenderTransformOrigin = new Point(0.5, 0.5);
                RotateTransform trans = new RotateTransform(0);
                uc.RenderTransform = trans;
            }
            var value = (bool)e.NewValue;
            if (value)
            {
                RotateAnimation.To = 180;
                uc.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, RotateAnimation);
            }
            else
            {
                RotateAnimation.To = 0;
                uc.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, RotateAnimation);
            }
        }
        #endregion

        #region CornerRadiusProperty Border圆角
        /// <summary>
        /// Border圆角
        /// </summary>
        public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.RegisterAttached(
            "CornerRadius", typeof(CornerRadius), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null));

        public static CornerRadius GetCornerRadius(DependencyObject d)
        {
            return (CornerRadius)d.GetValue(CornerRadiusProperty);
        }

        public static void SetCornerRadius(DependencyObject obj, CornerRadius value)
        {
            obj.SetValue(CornerRadiusProperty, value);
        }
        #endregion

        #region LabelProperty TextBox的头部Label
        /// <summary>
        /// TextBox的头部Label
        /// </summary>
        public static readonly DependencyProperty LabelProperty = DependencyProperty.RegisterAttached(
            "Label", typeof(string), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null));

        [AttachedPropertyBrowsableForType(typeof(TextBox))]
        public static string GetLabel(DependencyObject d)
        {
            return (string)d.GetValue(LabelProperty);
        }

        public static void SetLabel(DependencyObject obj, string value)
        {
            obj.SetValue(LabelProperty, value);
        }
        #endregion

        #region LabelTemplateProperty TextBox的头部Label模板
        /// <summary>
        /// TextBox的头部Label模板
        /// </summary>
        public static readonly DependencyProperty LabelTemplateProperty = DependencyProperty.RegisterAttached(
            "LabelTemplate", typeof(ControlTemplate), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null));

        [AttachedPropertyBrowsableForType(typeof(TextBox))]
        public static ControlTemplate GetLabelTemplate(DependencyObject d)
        {
            return (ControlTemplate)d.GetValue(LabelTemplateProperty);
        }

        public static void SetLabelTemplate(DependencyObject obj, ControlTemplate value)
        {
            obj.SetValue(LabelTemplateProperty, value);
        }
        #endregion

        
    }
}


Menu样式文件实现

    <!--背景透明的HeaderItem样式,带旋转动画-->
    <Style x:Key="TransparentHeaderMenuItem" TargetType="{x:Type MenuItem}">
        <Setter Property="BorderBrush" Value="{StaticResource MenuBorderBrush}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Background" Value="{StaticResource MenuBackground}"/>
        <Setter Property="Foreground" Value="{StaticResource TextForeground}"/>
        <Setter Property="FontSize" Value="{StaticResource FontSize}"/>
        <Setter Property="Margin" Value="2,0,2,0"/>
        <Setter Property="Height" Value="30"/>
        <Setter Property="local:ControlAttachProperty.FIconSize" Value="18"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type MenuItem}">
                    <Grid x:Name="Bg" VerticalAlignment="{TemplateBinding VerticalAlignment}">
                        <StackPanel Orientation="Horizontal" x:Name="border" VerticalAlignment="Center" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
                            <!--icon-->
                            <TextBlock x:Name="PART_Icon" Text="{TemplateBinding Icon}" Foreground="{TemplateBinding Foreground}" 
                                       local:ControlAttachProperty.AllowsAnimation="{Binding IsSubmenuOpen,RelativeSource={RelativeSource TemplatedParent}}"
                                       FontSize="{TemplateBinding local:ControlAttachProperty.FIconSize}" Style="{StaticResource FIcon}" />
                            <TextBlock x:Name="txtHeader" Margin="5 0 0 0" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Stretch" 
                                           Text="{TemplateBinding Header}" VerticalAlignment="Center" Grid.Column="1" Foreground="{TemplateBinding Foreground}"/>
                        </StackPanel>
                        <!--弹出子集菜单容器-->
                        <Popup x:Name="SubMenuPopup" AllowsTransparency="true" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" 
    									Placement="Bottom"  Focusable="false" VerticalOffset="0"
                                   PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}">
                            <Border Background="{TemplateBinding Background}"  CornerRadius="0" Margin="5" Effect="{StaticResource DefaultDropShadow}"
                                                BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                                <Grid x:Name="SubMenu" Grid.IsSharedSizeScope="True">
                                    <StackPanel Margin="10" IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
                                </Grid>
                            </Border>
                        </Popup>
                    </Grid>
                    <!--触发器-->
                    <ControlTemplate.Triggers>
                        <!--高亮状态-->
                        <Trigger Property="IsHighlighted" Value="true">
                            <Setter Property="Foreground" Value="{StaticResource MouseOverForeground}"></Setter>
                        </Trigger>
                        <Trigger Property="IsPressed" Value="true">
                            <Setter Property="Foreground" Value="{StaticResource PressedForeground}"></Setter>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="border" Value="{StaticResource DisableOpacity}" Property="Opacity"></Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

MainWindow样式实现

  <Menu Width="80" Height="30" Margin="3" Background="Transparent" >
      <MenuItem Header="展开菜单" Style="{StaticResource TransparentHeaderMenuItem}" Padding="0" Icon="&#xe61b;" >
          <MenuItem Style="{StaticResource TransparentHeaderMenuItem}" Icon="&#xe605;" Header="设置" />
          <MenuItem Style="{StaticResource TransparentHeaderMenuItem}" Icon="&#xe656;" Header="插件管理" />
          <MenuItem Style="{StaticResource TransparentHeaderMenuItem}" Icon="&#xe65e;"  Header="用户管理" />
          <MenuItem Style="{StaticResource TransparentHeaderMenuItem}" Icon="&#xe659;" Header="修改密码" />
          <MenuItem Style="{StaticResource TransparentHeaderMenuItem}" Icon="&#xe7c6;" Header="在线更新" />
          <Separator Background="SpringGreen" Style="{StaticResource HorizontalSeparatorStyle}"/>
          <MenuItem Style="{StaticResource TransparentHeaderMenuItem}" Icon="&#xe6d5;" Header="问题反馈" />
          <MenuItem Style="{StaticResource TransparentHeaderMenuItem}" Icon="&#xe65f;" Header="技术支持" />
          <MenuItem Style="{StaticResource TransparentHeaderMenuItem}" Icon="&#xe600;" Header="帮助" />
          <MenuItem Style="{StaticResource TransparentHeaderMenuItem}" Icon="&#xe622;" Header="关于" />
      </MenuItem>
  </Menu>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/799898.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Go: IM系统技术架构梳理

概述 整个IM系统的一般架构如下 我们这张图展示了整个IM系统的一般架构可见分为四层那最上面这一层是前端&#xff0c;包括哪些东西呢&#xff1f; 它包括两部分&#xff0c;第一部分是跟用户直接交互的比如说各种IOS APP, 各种安卓 APP还有各种 web APP 在浏览器里面打开的以…

区块链学习05-web3中solidity和move语言

Solidity 和 Move 语言的比较&#xff1a;Web3 开发中的两种选择 Solidity 和 Move 都是用于开发区块链平台智能合约的编程语言。它们具有一些相似之处&#xff0c;但也存在一些关键差异。 相似之处: Solidity 和 Move 都是图灵完备语言&#xff0c;这意味着它们可以表达计算…

Anything in Any Scene:无缝融入任何场景,实现逼真视频对象插入技术

现实世界的视频捕获虽然因其真实性而宝贵&#xff0c;但常常受限于长尾分布的问题&#xff0c;即常见场景过度呈现&#xff0c;而关键的罕见场景却鲜有记录。这导致了所谓的"分布外问题"&#xff0c;在模拟复杂环境光线、几何形状或达到高度逼真效果方面存在局限。传…

CentOS配置时钟服务

一、ntp协议 1.1 基础 NTP&#xff08;Network Time Protocol&#xff0c;网络时间协议&#xff09;是用于同步计算机网络中各个设备时间的协议。 下面了解一下 ntp 的配置选项 1.) iburst 功能: 通过发送一组八个数据包来加速初始同步。 用法: server 0.pool.ntp.org i…

Python实现简单的ui界面设计(小白入门)

引言&#xff1a; 当我们书写一个python程序时&#xff0c;我们在控制台输入信息时&#xff0c;往往多有不便&#xff0c;并且为了更加美观且直观的方式输入控制命令&#xff0c;我们常常设计一个ui界面&#xff0c;这样就能方便执行相关功能。如计算器、日历等界面。 正文&a…

Docker安装RabbitMQ(带web管理端)

1.拉取带web管理的镜像 可以拉取rabbitmq对应版本的web管理端&#xff0c;比如&#xff1a;rabbitmq:3.9.11-management&#xff0c;也可以直接拉取带web管理端的最新版本 rabbitmq:management. docker pull rabbitmq:3.9.11-management 注意&#xff1a;如果docker pull ra…

Linux目录网络设置远程工具的使用

文章目录 Linux目录虚拟机⽹络配置查看⽹络信息修改⽹络配置信息 虚拟机管理操作远程⼯具的使⽤ Linux目录 Linux的⽬录结构 Linux中的常⻅⽬录 Linux常⻅的⽬录结构&#xff0c;不同版本的Linux⽬录结构可能略有不同 Centos7的⽂件⽬录结构 Linux根⽬录下的常⻅⽬录及作⽤ …

C语言之qsort函数

一、qsort 1.库函数qsort qsort是库函数&#xff0c;直接可以用来排序数据&#xff0c;底层使用的是快速排序。 qsort函数可以排序任意类型的数据。 2.头文件 #include<stdlib.h> 3.参数讲解 void*类型的指针是无具体类型的指针&#xff0c;这种类型的指针的不能直接解…

COLING 2024 | AlphaFin:基于LLM的股票预测大模型,显著提高预测能力

COLING 2024 | AlphaFin&#xff1a;基于LLM的股票预测大模型&#xff0c;显著提高预测能力 发布于 2024-06-13 18:31:49 目前&#xff0c;机器学习和深度学习算法&#xff08;ML&DL&#xff09;已被广泛应用于股票趋势预测&#xff0c;并取得了显著进展。然而&#xff0c…

小霸王游戏卡是用什么编程的?

小霸王游戏卡曾经很流行。以超级马里奥为例&#xff0c;超级马里奥免费在线网址&#xff1a;https://supermarioplay.com/cn 游戏画面如下图&#xff1a; 这款游戏的编程语言是什么了&#xff1f; 汇编6502

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【25】【分布式事务】

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【25】【分布式事务】 本地事务事务的基本性质事务的隔离级别&#xff08;下面四个越往下&#xff0c;隔离级 别越高&#xff0c;并发能力越差&#xff09;事务的传播行为&#xff08;是否…

Linux系统调优与日志管理全面指南

文章目录 一、文件存储基础1.1 文件与硬盘存储单位1.2 文件数据与元信息1.3 inode机制查看文件名对应的inode号码有两种方式: 1.4 inode与硬盘空间1.5 特有现象 二、inode节点耗尽故障处理2.1 模拟inode节点耗尽故障 三、恢复误删除的文件3.1 恢复误删除的ext3文件EXT类型文件恢…

Zynq7000系列FPGA中的DDRI和DDRC

在AXI接口设计中&#xff0c;主端口&#xff08;Master Port&#xff09;和从端口&#xff08;Slave Port&#xff09;的交互是通过仲裁器&#xff08;Arbiter&#xff09;来管理的&#xff0c;以确保多个主设备能够有序地访问共享资源&#xff08;如DDR内存&#xff09;。这个…

C++20中的constinit说明符

constinit说明符断言(assert)变量具有静态初始化&#xff0c;即零初始化和常量初始化(zero initialization and constant initialization)&#xff0c;否则程序格式不正确(program is ill-formed)。 constinit说明符声明具有静态或线程存储持续时间(thread storage duration)的…

捷配笔记-PCB阻焊颜色对产品有什么影响?

阻焊层也称为阻焊层或阻焊剂。它是一种薄的聚合物层&#xff0c;应用于&#xff08;PCB&#xff09;。阻焊层的目的是保护PCB表面&#xff0c;并有助于防止焊桥。焊桥是两个导体之间的无意连接&#xff0c;通常是由于存在一小块焊料。需要注意的是&#xff0c;阻焊层被视为其单…

书生大模型实战营--L0关卡-Linux

一、SSH登录并完成nvidia-smi查看显卡以及安装pip install gradio4.29.0 二、完成vscode连接远程服务器 三、运行http://127.0.0.1:7860/

HTML表格表单及框架标签

一.表格标签 1.<table></table> 创建表格 2.<caption></caption> 表格的标题 3.<tr></tr>Table Row&#xff08;表格行&#xff09; 4.<td></td>Table Data&#xff08;表格数据&#xff09;其中有属性rowspan"2&quo…

单点触摸屏和多点触摸屏介绍以及原理简略

单点和多点触摸屏技术是现代触摸设备的基础&#xff0c;下述简单解释这两种技术及其差异。 单点触摸屏 单点触摸屏只能在某一时刻检测一个触摸点的位置。这种触摸屏适用于简单的触摸交互&#xff0c;如点击和拖动。 工作原理 单点触摸屏主要通过以下几种技术实现&#xff1…

SQL server 练习题2

课后作业 作业 1&#xff1a;自己查找方法&#xff0c;将 homework_1.xls 文件数据导入到 SQLServer 的 homework 数据库中。数据导入完成后&#xff0c;把表名统一改为&#xff1a;外卖表 如下所示&#xff1a; 作业 2&#xff1a;找出所有在 2020 年 5 月 1 日至 5 月 31 …

【Redis从0到1进阶】Redis 持久化

笔记内容来自B站博主《遇见狂神说》&#xff1a;Redis视频链接 Redis 是内存数据库&#xff0c;如果不将内存中的数据库状态保存到磁盘&#xff0c;那么一旦服务器进程退出&#xff0c;服务器中的数据库状态也会消失。所有Redis 提供了持久化功能&#xff01; 一、RDB&#xff…