软件编程
位置:首页>> 软件编程>> C#编程>> WPF实现环(圆)形菜单的示例代码

WPF实现环(圆)形菜单的示例代码

作者:驚鏵  发布时间:2022-05-07 18:46:34 

标签:WPF,环形,菜单

前言 

需要实现环(圆)形菜单。

效果预览(更多效果请下载源码体验):

WPF实现环(圆)形菜单的示例代码

实现代码

1.CircularMenuItemCustomControl.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WpfCircularMenu
{

[TemplatePart(Name = RotateTransformTemplateName, Type = typeof(RotateTransform))]
   public class CircularMenuItemCustomControl : Control
   {
       private static readonly Type _typeofSelf = typeof(CircularMenuItemCustomControl);
       private const string RotateTransformTemplateName = "PART_RotateTransform";
       private RotateTransform _angleRotateTransform;
       public double Angle
       {
           get { return (double)GetValue(AngleProperty); }
           set { SetValue(AngleProperty, value); }
       }

public static readonly DependencyProperty AngleProperty =
           DependencyProperty.Register("Angle", typeof(double), typeof(CircularMenuItemCustomControl), new UIPropertyMetadata(OnAngleChanged));

private static void OnAngleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
       {
           CircularMenuItemCustomControl control = (CircularMenuItemCustomControl)d;
           control.UpdateAngle();
       }
       void UpdateAngle()
       {
           if (_angleRotateTransform == null) return;
           _angleRotateTransform.Angle = Angle;
       }
       public string MenuTxt
       {
           get { return (string)GetValue(MenuTxtProperty); }
           set { SetValue(MenuTxtProperty, value); }
       }

public static readonly DependencyProperty MenuTxtProperty =
           DependencyProperty.Register("MenuTxt", typeof(string), typeof(CircularMenuItemCustomControl), new PropertyMetadata(string.Empty));

public Brush BackgroundColor
       {
           get { return (Brush)GetValue(BackgroundColorProperty); }
           set { SetValue(BackgroundColorProperty, value); }
       }
       public static readonly DependencyProperty BackgroundColorProperty =
          DependencyProperty.Register("BackgroundColor", typeof(Brush), typeof(CircularMenuItemCustomControl), new PropertyMetadata(null));

public ImageSource IconImage
       {
           get { return (ImageSource)GetValue(IconImageProperty); }
           set { SetValue(IconImageProperty, value); }
       }
       public static readonly DependencyProperty IconImageProperty =
           DependencyProperty.Register("IconImage", typeof(ImageSource), typeof(CircularMenuItemCustomControl), new PropertyMetadata(null));

static CircularMenuItemCustomControl()
       {
           DefaultStyleKeyProperty.OverrideMetadata(_typeofSelf, new FrameworkPropertyMetadata(_typeofSelf));
       }

public override void OnApplyTemplate()
       {
           base.OnApplyTemplate();
           _angleRotateTransform = GetTemplateChild(RotateTransformTemplateName) as RotateTransform;
           UpdateAngle();
       }

}
}

2.CircularMenuItemCustomControlStyle.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                   xmlns:local="clr-namespace:WpfCircularMenu">
   <Style TargetType="{x:Type local:CircularMenuItemCustomControl}">
       <Setter Property="Template">
           <Setter.Value>
               <ControlTemplate TargetType="local:CircularMenuItemCustomControl">
                   <Grid VerticalAlignment="Center">
                       <Grid.RenderTransform>
                           <RotateTransform x:Name="PART_RotateTransform" Angle="{TemplateBinding Angle}" CenterX="200" CenterY="200"></RotateTransform>
                       </Grid.RenderTransform>
                       <Path x:Name="PART_Path" Data="M 200,200 0,200 A 200,200 0 0 1 58.6,58.6z"
                                 Fill="{TemplateBinding BackgroundColor}" VerticalAlignment="Center"/>
                       <Image Source="{TemplateBinding IconImage}" RenderTransformOrigin="0.5,0.5"
                                  Margin="60,70,0,0"
                                  HorizontalAlignment="Left"
                                  VerticalAlignment="Center"
                                  Width="40" Height="40" >
                           <Image.RenderTransform>
                               <RotateTransform Angle="-70"/>
                           </Image.RenderTransform>
                       </Image>
                   </Grid>
                   <ControlTemplate.Triggers>
                       <Trigger Property="IsMouseOver" Value="true">
                           <Setter TargetName="PART_Path" Property="Fill" Value="#009AD8"/>
                           <Setter Property="Cursor" Value="Hand"/>
                       </Trigger>
                   </ControlTemplate.Triggers>
               </ControlTemplate>
           </Setter.Value>
       </Setter>
</Style>
</ResourceDictionary>

3.MainWindow.xaml

<Window x:Class="WpfCircularMenu.MainWindow"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       xmlns:local="clr-namespace:WpfCircularMenu"
       mc:Ignorable="d"
       Title="MainWindow" Height="850" Width="1200"
       Background="Black"
       SnapsToDevicePixels="True"
       TextOptions.TextFormattingMode="Display"
       UseLayoutRounding="True">
   <Window.Resources>
       <Storyboard x:Key="CheckedStoryboard">
           <DoubleAnimation Storyboard.TargetName="PART_EllipseGeometry"
                            Storyboard.TargetProperty="RadiusX"
                            Duration="00:00:0.4" To="200"/>
           <DoubleAnimation Storyboard.TargetName="PART_EllipseGeometry"
                            Storyboard.TargetProperty="RadiusY"
                            Duration="00:00:0.4" To="200"/>
       </Storyboard>
       <Storyboard x:Key="UncheckedStoryboard">
           <DoubleAnimation Storyboard.TargetName="PART_EllipseGeometry"
                            Storyboard.TargetProperty="RadiusX"
                            Duration="00:00:0.3" To="0"/>
           <DoubleAnimation Storyboard.TargetName="PART_EllipseGeometry"
                            Storyboard.TargetProperty="RadiusY"
                            Duration="00:00:0.3" To="0"/>
       </Storyboard>
   </Window.Resources>
   <Viewbox>
       <Grid Height="768" Width="1024">
           <Canvas>
               <ItemsControl ItemsSource="{Binding MenuArray,RelativeSource={RelativeSource AncestorType=local:MainWindow}}"
                             Canvas.Left="150" Canvas.Top="150">
                   <ItemsControl.Clip>
                       <EllipseGeometry x:Name="PART_EllipseGeometry" RadiusX="0" RadiusY="0" Center="200,200"></EllipseGeometry>
                   </ItemsControl.Clip>
                   <ItemsControl.ItemTemplate>
                       <DataTemplate>
                           <local:CircularMenuItemCustomControl Angle="{Binding Angle}" MenuTxt="{Binding Title}"
                                                             BackgroundColor="{Binding FillColor}" IconImage="{Binding IconImage}"/>
                       </DataTemplate>
                   </ItemsControl.ItemTemplate>
                   <ItemsControl.ItemsPanel>
                       <ItemsPanelTemplate>
                           <Grid/>
                       </ItemsPanelTemplate>
                   </ItemsControl.ItemsPanel>
               </ItemsControl>

<ToggleButton Canvas.Left="300" Canvas.Top="300" Cursor="Hand">
                   <ToggleButton.Template>
                       <ControlTemplate TargetType="ToggleButton">
                           <Grid>
                               <Ellipse x:Name="PART_Ellipse" Width="100" Height="100" Fill="#009AD8" ToolTip="关闭"/>
                               <Path x:Name="PART_Path" Data="M734.618 760.269c-24.013 24.013-62.925 24.013-86.886 0l-135.731-155.136-135.731 155.085c-24.013 24.013-62.925 24.013-86.886 0-24.013-24.013-24.013-62.925 0-86.886l141.21-161.28-141.261-161.382c-24.013-24.013-24.013-62.874 0-86.886s62.874-24.013 86.886 0l135.782 155.187 135.731-155.187c24.013-24.013 62.874-24.013 86.886 0s24.013 62.925 0 86.886l-141.21 161.382 141.21 161.28c24.013 24.013 24.013 62.925 0 86.938z"
                                     Fill="White" Stretch="Fill" Width="20" Height="20" RenderTransformOrigin="0.5,0.5" IsHitTestVisible="False">
                               </Path>
                           </Grid>
                           <ControlTemplate.Triggers>
                               <Trigger Property="IsChecked" Value="false">
                                   <Setter TargetName="PART_Path" Property="RenderTransform">
                                       <Setter.Value>
                                           <RotateTransform Angle="45"/>
                                       </Setter.Value>
                                   </Setter>
                                   <Setter Property="ToolTip" TargetName="PART_Ellipse" Value="展开"/>
                               </Trigger>
                           </ControlTemplate.Triggers>
                       </ControlTemplate>
                   </ToggleButton.Template>
                   <ToggleButton.Triggers>
                       <EventTrigger RoutedEvent="ToggleButton.Checked">
                           <BeginStoryboard Storyboard="{StaticResource CheckedStoryboard}"/>
                       </EventTrigger>
                       <EventTrigger RoutedEvent="ToggleButton.Unchecked">
                           <BeginStoryboard Storyboard="{StaticResource UncheckedStoryboard}"/>
                       </EventTrigger>
                   </ToggleButton.Triggers>
               </ToggleButton>
               <TextBlock Text="微信公众号:WPF开发者" FontSize="40"
                          Foreground="#A9CC32" FontWeight="Bold"
                          Canvas.Top="50"/>
               <Image Source="Images/gzh.png" Canvas.Left="140" Canvas.Bottom="40"/>
           </Canvas>
       </Grid>
   </Viewbox>
</Window>

4.MainWindow.xaml.cs

<Window x:Class="WpfCircularMenu.MainWindow"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       xmlns:local="clr-namespace:WpfCircularMenu"
       mc:Ignorable="d"
       Title="MainWindow" Height="850" Width="1200"
       Background="Black"
       SnapsToDevicePixels="True"
       TextOptions.TextFormattingMode="Display"
       UseLayoutRounding="True">
   <Window.Resources>
       <Storyboard x:Key="CheckedStoryboard">
           <DoubleAnimation Storyboard.TargetName="PART_EllipseGeometry"
                            Storyboard.TargetProperty="RadiusX"
                            Duration="00:00:0.4" To="200"/>
           <DoubleAnimation Storyboard.TargetName="PART_EllipseGeometry"
                            Storyboard.TargetProperty="RadiusY"
                            Duration="00:00:0.4" To="200"/>
       </Storyboard>
       <Storyboard x:Key="UncheckedStoryboard">
           <DoubleAnimation Storyboard.TargetName="PART_EllipseGeometry"
                            Storyboard.TargetProperty="RadiusX"
                            Duration="00:00:0.3" To="0"/>
           <DoubleAnimation Storyboard.TargetName="PART_EllipseGeometry"
                            Storyboard.TargetProperty="RadiusY"
                            Duration="00:00:0.3" To="0"/>
       </Storyboard>
   </Window.Resources>
   <Viewbox>
       <Grid Height="768" Width="1024">
           <Canvas>
               <ItemsControl ItemsSource="{Binding MenuArray,RelativeSource={RelativeSource AncestorType=local:MainWindow}}"
                             Canvas.Left="150" Canvas.Top="150">
                   <ItemsControl.Clip>
                       <EllipseGeometry x:Name="PART_EllipseGeometry" RadiusX="0" RadiusY="0" Center="200,200"></EllipseGeometry>
                   </ItemsControl.Clip>
                   <ItemsControl.ItemTemplate>
                       <DataTemplate>
                           <local:CircularMenuItemCustomControl Angle="{Binding Angle}" MenuTxt="{Binding Title}"
                                                             BackgroundColor="{Binding FillColor}" IconImage="{Binding IconImage}"/>
                       </DataTemplate>
                   </ItemsControl.ItemTemplate>
                   <ItemsControl.ItemsPanel>
                       <ItemsPanelTemplate>
                           <Grid/>
                       </ItemsPanelTemplate>
                   </ItemsControl.ItemsPanel>
               </ItemsControl>

<ToggleButton Canvas.Left="300" Canvas.Top="300" Cursor="Hand">
                   <ToggleButton.Template>
                       <ControlTemplate TargetType="ToggleButton">
                           <Grid>
                               <Ellipse x:Name="PART_Ellipse" Width="100" Height="100" Fill="#009AD8" ToolTip="关闭"/>
                               <Path x:Name="PART_Path" Data="M734.618 760.269c-24.013 24.013-62.925 24.013-86.886 0l-135.731-155.136-135.731 155.085c-24.013 24.013-62.925 24.013-86.886 0-24.013-24.013-24.013-62.925 0-86.886l141.21-161.28-141.261-161.382c-24.013-24.013-24.013-62.874 0-86.886s62.874-24.013 86.886 0l135.782 155.187 135.731-155.187c24.013-24.013 62.874-24.013 86.886 0s24.013 62.925 0 86.886l-141.21 161.382 141.21 161.28c24.013 24.013 24.013 62.925 0 86.938z"
                                     Fill="White" Stretch="Fill" Width="20" Height="20" RenderTransformOrigin="0.5,0.5" IsHitTestVisible="False">
                               </Path>
                           </Grid>
                           <ControlTemplate.Triggers>
                               <Trigger Property="IsChecked" Value="false">
                                   <Setter TargetName="PART_Path" Property="RenderTransform">
                                       <Setter.Value>
                                           <RotateTransform Angle="45"/>
                                       </Setter.Value>
                                   </Setter>
                                   <Setter Property="ToolTip" TargetName="PART_Ellipse" Value="展开"/>
                               </Trigger>
                           </ControlTemplate.Triggers>
                       </ControlTemplate>
                   </ToggleButton.Template>
                   <ToggleButton.Triggers>
                       <EventTrigger RoutedEvent="ToggleButton.Checked">
                           <BeginStoryboard Storyboard="{StaticResource CheckedStoryboard}"/>
                       </EventTrigger>
                       <EventTrigger RoutedEvent="ToggleButton.Unchecked">
                           <BeginStoryboard Storyboard="{StaticResource UncheckedStoryboard}"/>
                       </EventTrigger>
                   </ToggleButton.Triggers>
               </ToggleButton>
               <TextBlock Text="微信公众号:WPF开发者" FontSize="40"
                          Foreground="#A9CC32" FontWeight="Bold"
                          Canvas.Top="50"/>
               <Image Source="Images/gzh.png" Canvas.Left="140" Canvas.Bottom="40"/>
           </Canvas>
       </Grid>
   </Viewbox>
</Window>

来源:https://www.cnblogs.com/yanjinhua/p/14919516.html

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com