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>到此这篇关于wpf实现环(圆)形菜单的示例代码的文章就介绍到这了,更多相关wpf菜单内容请搜索萬仟网以前的文章或继续浏览下面的相关文章希望大家以后多多支持萬仟网!
看完文章,还可以扫描下面的二维码下载快手极速版领4元红包
除了扫码领红包之外,大家还可以在快手极速版做签到,看视频,做任务,参与抽奖,邀请好友赚钱)。
邀请两个好友奖最高196元,如下图所示:







