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


    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>
  • 相关阅读:
    css中vertical-align(垂直对齐)的使用
    CSS教程:div垂直居中的N种方法[转]
    前后端分离开发部署模式
    <a>标签的href和onclick属性
    css 字体样式
    谷歌开发者工具界面介绍
    cps和dsp渠道手法的研究
    网络资源汇总
    DataWorks(数据工场)
    vue入门学习笔记
  • 原文地址:https://www.cnblogs.com/yzhyingcool/p/16389928.html
Copyright © 2020-2023  润新知