ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【WPF】自定义下拉菜单控件DropDownButton的实现,下拉箭头旋转,ContextMenu、MenuItem的样式及FontAwesome字体图标的引用

2022-06-19 09:31:58  阅读:311  来源: 互联网

标签:System 控件 自定义 Menu DropDownButton ani using new 下拉菜单


DropDownButton控件自定义,ContextMenu、MenuItem的样式及FontAwesome字体图标的引用

效果如图,弹出收起动画等的效果还没做。

 

xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:FTools.Controls">

    <Style TargetType="{x:Type local:DropDownButton}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:DropDownButton}">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="Storyboard1">
                            <DoubleAnimation Storyboard.TargetName="img" Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(RotateTransform.Angle)" 
                                                To="-180" Duration="0:0:0.2"  FillBehavior="HoldEnd" />
                        </Storyboard>
                        <Storyboard x:Key="Storyboard2">
                            <DoubleAnimation Storyboard.TargetName="img" Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(RotateTransform.Angle)" 
                                                To="0" Duration="0:0:0.2"  FillBehavior="HoldEnd" />
                        </Storyboard>
                    </ControlTemplate.Resources>
                    <Grid>
                        <Border x:Name="bd" Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            CornerRadius="5"
                            Width="{TemplateBinding Width}">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="8*"/>
                                    <ColumnDefinition Width="2*" MinWidth="20"/>
                                </Grid.ColumnDefinitions>
                                <TextBlock Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}"
                                       VerticalAlignment="Center"
                                       HorizontalAlignment="Center"
                                       Margin="5,0,0,0"
                                       />
                                <Path x:Name="Part_Arrow" Grid.Column="1" Data="M0,0 L4,4 8,0 Z"  VerticalAlignment="Center" HorizontalAlignment="Center"
                                      Fill="{TemplateBinding Foreground}" Margin="0,0,5,0">
                                    <Path.LayoutTransform>
                                        <RotateTransform  Angle="0"/>
                                    </Path.LayoutTransform>
                                </Path>
                            </Grid>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger SourceName="bd" Property="IsMouseOver" Value="True">
                            <Setter TargetName="bd" Property="Background" Value="LightGray"/>
                        </Trigger>
                        
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!--FontAwesome字体下载及在WPF中的使用
    https://fontawesome.com/
    ##########下载
    下载地址:https://fontawesome.com/download  
    下载内容:Free For Web
    ##########使用
    双击**.ttf,进入安装页可以看到“字体名称……”,记住字体名称
    将 **.ttf复制到wpf工程自定内资源目录,FontFamily属性值=资源目录/#字体名称,如"../Resources/#Font Awesome 6 Free Solid"  
    Text的值为 FontAwesome Icon的十六进制 Unicode值,如 Text="&#xf0c5;"
    -->
    <Style x:Key="FontAwesome">
        <Setter Property="TextElement.FontFamily" Value="../Resources/#Font Awesome 6 Free Solid" />
        <Setter Property="TextBlock.Width" Value="20"></Setter>
        <Setter Property="TextBlock.Height" Value="20"></Setter>
        <Setter Property="TextBlock.TextAlignment" Value="Center"></Setter>
        <Setter Property="TextBlock.FontSize" Value="15"></Setter>
    </Style>
    <!--MenuItem样式,DropDownButton控件中嵌套ContextMenu中MenuItem引用此样式-->
    <Style x:Key="FTools.Controls.DropDownButton.MenuItemStyle" TargetType="{x:Type MenuItem}">
        <!--<Setter Property="OverridesDefaultStyle" Value="True"/>-->
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type MenuItem}">
                    <Border x:Name="mi_Border" Width="{TemplateBinding Width}" Background="Transparent" CornerRadius="5">
                        <StackPanel Orientation="Horizontal" >
                            <Border VerticalAlignment="Center" BorderBrush="{TemplateBinding Foreground }"  BorderThickness="0,0,0.5,0">
                                <TextBlock x:Name="mi_Icon" Text="{TemplateBinding Icon}" Foreground="{TemplateBinding Foreground}" Style="{DynamicResource FontAwesome}" Margin="5"/>
                            </Border>
                            <ContentPresenter 
                                Margin="5"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Center"
                                ContentSource= "Header"
                                RecognizesAccessKey="True"
                                />
                        </StackPanel>   
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger SourceName="mi_Border" Property="IsMouseOver" Value="True">
                            <!--<Setter TargetName="mi_Icon"  Property="Foreground" Value="Black"/>-->
                            <Setter TargetName="mi_Border" Property="Background" Value="lightgray"/>
                        </Trigger> 
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter> 
    </Style>
    <!--ContextMenu样式,DropDownButton控件中嵌套ContextMenu引用此样式-->
    <Style x:Key="FTools.Controls.DropDownButton.ContextMenuStyle" TargetType="ContextMenu">
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="OverridesDefaultStyle" Value="True" />
        <!--<Setter Property="Grid.IsSharedSizeScope" Value="True" />-->
        <Setter Property="HasDropShadow" Value="True" />
        <Setter Property="Foreground" Value="Black"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ContextMenu">
                    <Border Background="White" BorderBrush="DarkGray" BorderThickness="0.7" CornerRadius="5" Width="{TemplateBinding Width}">
                        <ItemsPresenter/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

C#代码:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace FTools.Controls
{
    [TemplatePart(Name = DropDownButton.part_Arrow, Type = typeof(Popup))]
    public class DropDownButton : ToggleButton
    {
        static DropDownButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DropDownButton), new FrameworkPropertyMetadata(typeof(DropDownButton)));
        }
        public DropDownButton()
        {
            Binding binding = new Binding("Menu.IsOpen");
            binding.Source = this;
            this.SetBinding(IsCheckedProperty, binding);
            DataContextChanged += (sender, args) =>
            {
                if (Menu != null)
                    Menu.DataContext = DataContext;
            };
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this.path=GetTemplateChild(part_Arrow) as Path;

            if (this.path != null && this.Menu!=null)
                this.Menu.Closed += this.Menu_Closed;
            if (this.path != null && this.Menu != null)
                this.Menu.Opened += this.Menu_Opened;

        }
        public const string part_Arrow = "Part_Arrow";

        private Path path;

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text",typeof(string), typeof(DropDownButton));
        public static readonly DependencyProperty MenuProperty = DependencyProperty.Register("Menu",
      typeof(ContextMenu), typeof(DropDownButton), new UIPropertyMetadata(null, OnMenuChanged));

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
        public ContextMenu Menu
        {
            get { return (ContextMenu)GetValue(MenuProperty); }
            set { SetValue(MenuProperty, value); }
        }

        private static void OnMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var dropDownButton = (DropDownButton)d;
            var contextMenu = (ContextMenu)e.NewValue;
            contextMenu.DataContext = dropDownButton.DataContext;
        }

        protected override void OnClick()
        {
            if (Menu != null)
            {
                Menu.PlacementTarget = this;
                Menu.Placement = PlacementMode.Bottom;
                Menu.IsOpen = true;
                Menu.Background = new System.Windows.Media.SolidColorBrush(Color.FromRgb(255,255,255));
            }
        }

        private void Menu_Opened(object sender, EventArgs e)
        {
            RotateTransform rotateTransform = new RotateTransform();
            this.path.LayoutTransform = rotateTransform;
            DoubleAnimation ani = new DoubleAnimation();
            ani.From = 0;
            ani.To = -180;
            ani.Duration = TimeSpan.FromSeconds(0.5);
            Storyboard storyboard = new Storyboard();
            storyboard.Children.Add(ani);
            Storyboard.SetTarget(ani, this.path);
            Storyboard.SetTargetProperty(ani, new PropertyPath("(FrameworkElement.LayoutTransform).(RotateTransform.Angle)"));
            storyboard.Begin();
        }
        private void Menu_Closed(object sender, EventArgs e)
        {
            RotateTransform rotateTransform = new RotateTransform();
            this.path.LayoutTransform = rotateTransform;
            DoubleAnimation ani = new DoubleAnimation
            {
                From = -180,
                To = 0,
                Duration = TimeSpan.FromSeconds(0.5)
            };
            Storyboard storyboard = new Storyboard();
            storyboard.Children.Add(ani);
            Storyboard.SetTarget(ani, this.path);
            Storyboard.SetTargetProperty(ani, new PropertyPath("(FrameworkElement.LayoutTransform).(RotateTransform.Angle)"));
            storyboard.Begin();
        }
    }
}

 

控件的使用Xaml

                                <FControls:DropDownButton Grid.Column="6" Background="White" Foreground="{DynamicResource foregroundColor}"
                                                          FontFamily="宋体" FontSize="12"
                                                          Width="80"
                                                          Text="开始操作"
                                                          HorizontalAlignment="Right"
                                                          >
                                    <FControls:DropDownButton.Menu>
                                        <ContextMenu Style="{DynamicResource FTools.Controls.DropDownButton.ContextMenuStyle}" Width="Auto">
                                            <MenuItem Style="{DynamicResource FTools.Controls.DropDownButton.MenuItemStyle}" x:Name="miPathClean" Header="复制文件/文件夹" Icon="&#xf0c5;" Foreground="{StaticResource foregroundColor}"/>
                                            <MenuItem Style="{DynamicResource FTools.Controls.DropDownButton.MenuItemStyle}" x:Name="miPathExport" Header="移动文件/文件夹" Icon="&#xf56e;" Foreground="{StaticResource foregroundColor}"/>
                                            <MenuItem Style="{DynamicResource FTools.Controls.DropDownButton.MenuItemStyle}" x:Name="miPathInput" Header="重命名文件/文件夹" Icon="&#xf573;" Foreground="{StaticResource foregroundColor}"/>
                                        </ContextMenu>
                                    </FControls:DropDownButton.Menu>
                                </FControls:DropDownButton>

 

标签:System,控件,自定义,Menu,DropDownButton,ani,using,new,下拉菜单
来源: https://www.cnblogs.com/yzhyingcool/p/16389928.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有