当前位置:首页 > 谈天说地 > 正文内容

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

34资源网2022年07月30日 10:57179
站长推荐》》》》》摆摊地推这两款软件,一个月3000元-3万元轻松实现《《《《《站长推荐

前言 

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

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

实现代码

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菜单内容请搜索萬仟网以前的文章或继续浏览下面的相关文章希望大家以后多多支持萬仟网!

看完文章,还可以用支付宝扫描下面的二维码领取一个支付宝红包,目前可领1-88元不等

支付宝红包二维码

除了扫码可以领取之外,大家还可以(复制 720087999 打开✔支付宝✔去搜索, h`o`n.g.包哪里来,动动手指就能领)。

看下图所示是好多参与这次活动领取红包的朋友:

支付宝红包

扫描二维码推送至手机访问。

版权声明:本文由34楼发布,如需转载请注明出处。

本文链接:https://www.34l.com/post/20050.html

分享给朋友:

相关文章

打败你的不一定是你的对手,有可能是一个过路人
打败你的不一定是你的对手,有可能是一个过路人

有句话叫做“羊毛出在狗身上,由猪买单”现阶段打败你的不一定是对手而是一个过路人。最近,尼康退出中国,裁员两千人!很多人以为尼康是被同行打败,没想到居然是毫无相关的行业。尼康直接宣布破产的真相:受智能手机普及的影响!有一部很牛的科幻小说,名字...

适合年轻人创业项目,投资小又赚钱多的项目推荐
适合年轻人创业项目,投资小又赚钱多的项目推荐

社会在发展,科技在更新,生活也在发生着翻天覆地的变化。但是,唯一不变的是,年轻人创业的心,一直都没有变过。每个时代都会有很多想创业的年轻人,只是每个时代的年轻人创业项目都有所不同,那么,今天我们就说说适合现在年轻人创业的项目。下面小编整理了...

谈2022年平衡发展策略,我们要平衡的发展
谈2022年平衡发展策略,我们要平衡的发展

2022年解决方案的第二个关键词叫平衡。我们要平衡的发展,长期的发展。你的个人生活,你的公司事业,还有国家的形势,我觉得一定要平衡的去发展,不能说我只赚钱,身体就搞垮,或者说我只赚快钱,但是不关心国家的形势。你看,密室逃脱这个行业,上周国家...

带货直播运营怎么做(直播公司盈利模式)
带货直播运营怎么做(直播公司盈利模式)

直播网红千千万,谁能争当NO.1?随着直播崛起,越来越多的人想要入场分一杯羹,BUT,80%的人都不懂直播运营的内容法则。那么,新手主播怎么玩才能快速脱颖而出呢?掌握这四大直播运营的内容规则,人气轻松翻倍!1. 直播内容多样化主播想要保证直...

视频号怎么开通微信小商店技巧流程方法分享
视频号怎么开通微信小商店技巧流程方法分享

这两年直播的风口一直高居不下,微信终于也跟上了直播热潮,视频号直播新增购物车功能,已经开通了小商店的视频号,可以在直播中上架小商店商品,直播过程可以展示并售卖商品。视频号直播带货无疑让更多创作者加入其中,同时也意味着视频号功能的进一步完善,...

裁员,爱奇艺穿越生死线
裁员,爱奇艺穿越生死线

图源:摄图网 编者按:本文来自微信公众号霞光社(ID:Globalinsights)),作者:麻吉、郭照川、韩夏,创业邦经授权转载 霞光社从多位爱奇艺员工处了解到,本轮裁员罕见覆盖了爱奇艺所有部门,从影业、IP、游戏、电商部门,甚至到经纪...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。