WPF实现环(圆)形菜单
程序员文章站
2022-05-18 09:17:38
WPF开发者QQ群: 340500857 | 微信群 -> 进入公众号主页 加入组织 每日一笑 刚在路上看见了小学同学正在捡矿泉水瓶子,心里很不是滋味,想不到昔日的玩伴如今竟然成了竞争对手。 前言 需要实现环(圆)形菜单。 欢迎转发、分享、点赞,谢谢大家~。 效果预览(更多效果请下载源码体验): 一 ......
wpf开发者qq群: 340500857 | 微信群 -> 进入公众号主页 加入组织
每日一笑
刚在路上看见了小学同学正在捡矿泉水瓶子,心里很不是滋味,想不到昔日的玩伴如今竟然成了竞争对手。
前言
需要实现环(圆)形菜单。
欢迎转发、分享、点赞,谢谢大家~。
效果预览(更多效果请下载源码体验):
一、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(); } } }
二、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>
三、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>
四、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开发者qq群: 340500857
blogs: https://www.cnblogs.com/yanjinhua/p/14345136.html
源码github:https://github.com/yanjinhuagood/wpfdevelopers.git
gitee:https://gitee.com/yanjinhua/wpfdevelopers.git
上一篇: jQuery 动画效果 与 动画队列
下一篇: linux小白的入门和目标。