WPF实现环(圆)形菜单的示例代码
作者:驚鏵 发布时间:2022-05-07 18:46:34
标签: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


猜你喜欢
- 上次简单的说了一下CoordinatorLayout的基本用法(android特性之CoordinatorLayout用法探析实例)。其中C
- 前言本文主要学习函数的相关内容。1、函数是什么? * 中对函数的定义:子程序在计算机科学中,子程序(英语:Subroutine, proc
- 本文实例讲述了C#文件分割的方法。分享给大家供大家参考。具体如下:1. 小文件分割(适用于小于等于64M的文件):using System;
- 本文分为俩部分:第一部分介绍如何给Eclipse安装Spring Boot开发插件spring tool suite(简称STS);第二部分
- 本文实例为大家分享了Java实现通讯录管理系统的具体代码,供大家参考,具体内容如下题目:1、完成一个通讯录,需求:(1)添加联系人(联系人:
- package dao;import java.sql.*;public class BaseDao { //oracle//&n
- 本文实例总结了 Android中Notification用法。分享给大家供大家参考,具体如下:我们在用手机的时候,如果来了短信,而我们没有点
- 十进制转二进制正整数转二进制除2取余,逆序排列,高位补零。示例:十进制255 = 二进制1111 1111计算过程:255/2=127===
- 一、PriorityQueue的数据结构JDK7中PriorityQueue(优先级队列)的数据结构是二叉堆。准确的说是一个最小堆。二叉堆是
- Android 侧滑菜单的实现,参考网上的代码,实现侧滑菜单。最重要的是这个动画类UgcAnimations,如何使用动画类来侧滑的封装Fl
- 本文介绍了springcloud Feign的Hystrix支持,分享给大家,具体如下:一、Feign client中加入Hystrix的f
- 一、Intent的用途Intent主要有以下几种重要用途: 1. 启动Activity:可以将Intent对象传递给startActivit
- Purpose开发人员在合作的时候经常遇到以下场景:1.开发人员A在自己的本地数据库做了一些表结构的改动,并根据这些改动调整了DAO层的代码
- 本文实例为大家分享了C#实现QQ聊天窗口的具体代码,供大家参考,具体内容如下效果图:using System;using System.Co
- “热更新”、“热部署”相信对于混合式开发的童鞋一定不陌生,那么APP怎么避免每次升级都要在APP应用商店发布呢?这里就用到了混合
- 首先安装consul环境,参照之前的文章:https://www.jb51.net/article/141789.htm项目规划,2个服务端
- 接着上一篇继续,老铁们1.检查数组的有序性给定一个整型数组, 判断是否该数组是有序的(升序) public static bo
- 前2天有读者问到是否有带分页功能的表格控件,今天分页功能的表格控件详细解析。PaginatedDataTablePaginatedDataT
- # 看题目是不是很绕,这个我也不知道怎么才能更简单的表达了# 先看代码:public class Common {public static
- 零、Gallery的使用回顾我们有时候在iPhone手机上或者Windows上面看到动态的图片,可以通过鼠标或者手指触摸来移动它,产生动态的