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

avatar
作者
猴君
阅读量:4

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

一、创建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> 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!