欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

WPF 动态添加控件以及样式字典的引用(Style introduction)

程序员文章站 2022-03-22 14:34:58
我们想要达到的结果是,绑定多个Checkbox然后我们还可以获取它是否被选中,其实很简单,我们只要找到那几个关键的对象就可以了。 下面是Ui,其中定义了一个WrapPanel来存放CheckBox,还有两个按钮,用于测试相关功能。 在动态添加Checkbox中我们定义了一个CheckBox数组,此后 ......

  我们想要达到的结果是,绑定多个checkbox然后我们还可以获取它是否被选中,其实很简单,我们只要找到那几个关键的对象就可以了。

  下面是ui,其中定义了一个wrappanel来存放checkbox,还有两个按钮,用于测试相关功能。

<window x:class="wpfapplication1.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:wpfapplication1"
        mc:ignorable="d"
        title="mainwindow" height="350" width="525">
    <grid  name="div" >
        <stackpanel margin="0,50,0,0" orientation="horizontal"  horizontalalignment="center">
            <stackpanel>
                <button content="动态添加多个checkbox控件" height="20" padding="15,1,15,2" x:name="btnadd" click="btnadd_click"></button>
            </stackpanel>

        </stackpanel>

        <scrollviewer scrollviewer.verticalscrollbarvisibility="auto" height="150">
            <border   borderbrush="#797979" borderthickness="1" margin="5,0,5,5">
                <wrappanel x:name="addcheckbox"/>
            </border>
        </scrollviewer>
        <button x:name="button" content="button" horizontalalignment="left" margin="37,261,0,0" verticalalignment="top" width="75" click="button_click"/>
        <button x:name="button1" content="button" horizontalalignment="left" margin="379,50,0,0" verticalalignment="top" width="75" click="button1_click"/>
    </grid>
</window>

  在动态添加checkbox中我们定义了一个checkbox数组,此后又实例化了thickness对象,它是用于描述矩形周围的粗细,然后我们又循环了数组的长度来进行添加(对其中name为addcheckbox的控件),至此,checkbox已动态添加。

  那如何删除呢?我们依旧需要获取那个名为addcheckbox的控件的儿子们(children)来进行remove。请看以下代码片段。

private void button1_click(object sender, routedeventargs e)
        {
            for (int i = 0; i < addcheckbox.children.count;)
            {
                this.addcheckbox.children.remove(addcheckbox.children[i]);
            }
        }

循环其中的值也是非常的简单,因为我们在上面绑定的时候,已经给它的content或者是datacontext都赋值了,所以我们只要获取就ok了。

private void button_click(object sender, routedeventargs e)
        {
            foreach (uielement item in addcheckbox.children)
            {
                if (item is checkbox)
                {
                    checkbox checkbox = (item as checkbox);
                    if (checkbox.ischecked == true)
                    {
                        messagebox.show(checkbox.content.tostring());
                    }
                }
            }
        }

 最后生成出来的效果是这样的,是不是非常丑,那我教你如何进行简单的美化。

WPF 动态添加控件以及样式字典的引用(Style introduction)

 在我们添加checkbox的时候有两种引入方式,一种是 checkbox.style = resources["noticebox"] as style; 另一种的话是 style style = (style)this.findresource("noticebutton"); 那两者有什么区别呢?

第一个是必须将资源文件引用到当前页面,第二种的是在app.xaml进行查找不包括app.xaml中引入的(外部的资源文件)。下面我们写一个checkbox样式在app,xaml中。

<application x:class="wpfapplication1.app"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:wpfapplication1"
             startupuri="mainwindow.xaml">

    <application.resources>
        <style x:key="checkboxswitchstyle" targettype="checkbox">
            <setter property="ischecked" value="false"/>
            <setter property="cursor" value="hand"/>
            <setter property="fontfamily" value="/mestoolintegration;component/fonts/#iconfont"/>
            <setter property="background" value="#ffffff"/>
            <setter property="template">
                <setter.value>
                    <controltemplate targettype="checkbox">
                        <border width="54" name="checktruebg" height="22" borderthickness="1" background="#ffffff"  cornerradius="10" borderbrush="#acacac" >
                            <grid>
                                <border borderthickness="1" background="#acacac" x:name="border" width="20" height="20" cornerradius="9" verticalalignment="center" horizontalalignment="left" margin="0"  >
                                    <border.rendertransform>
                                        <translatetransform  x="1"/>
                                    </border.rendertransform>
                                </border>
                                <textblock x:name="txt" text="{templatebinding content}" fontfamily="iconfont"  fontsize="{templatebinding fontsize}" margin="6.996,2.798,0,2.798" verticalalignment="stretch" foreground="#acacac" horizontalalignment="left" >
                                    <textblock.rendertransform>
                                        <translatetransform   x="17"></translatetransform>
                                    </textblock.rendertransform>
                                </textblock>
                            </grid>
                        </border>
                        <controltemplate.triggers>
                            <trigger property="ischecked" value="true">
                                <setter property="background" targetname="checktruebg"  value="#5fb878"/>
                                <setter property="foreground" targetname="txt"  value="#ffffff"/>
                                <setter property="background" targetname="border"  value="#ffffff"/>
                                <setter property="text" targetname="txt" value="{binding tag,relativesource={relativesource templatedparent}}"/>
                                <trigger.enteractions>
                                    <beginstoryboard>
                                        <storyboard>
                                            <doubleanimation storyboard.targetname="border" storyboard.targetproperty="(uielement.rendertransform).(translatetransform.x)" to="32" duration="00:00:0.2"/>
                                            <doubleanimation storyboard.targetname="txt" storyboard.targetproperty="(uielement.rendertransform).(translatetransform.x)" to="0" duration="00:00:0.2"/>
                                        </storyboard>
                                    </beginstoryboard>
                                </trigger.enteractions>
                                <trigger.exitactions>
                                    <beginstoryboard>
                                        <storyboard>
                                            <doubleanimation storyboard.targetname="border" storyboard.targetproperty="(uielement.rendertransform).(translatetransform.x)" to="0" duration="00:00:0.2"/>
                                            <doubleanimation storyboard.targetname="txt" storyboard.targetproperty="(uielement.rendertransform).(translatetransform.x)" to="17" duration="00:00:0.2"/>
                                        </storyboard>
                                    </beginstoryboard>
                                </trigger.exitactions>
                            </trigger>
                            <trigger property="ischecked" value="false">
                                <setter property="text" targetname="txt" value="{binding content,relativesource={relativesource templatedparent}}"/>
                            </trigger>
                        </controltemplate.triggers>
                    </controltemplate>
                </setter.value>
            </setter>
        </style>
    </application.resources>
</application>

就这样我们在生成checkbox中进行配置,代码如下。

private void btnadd_click(object sender, routedeventargs e)
        {
            int num = 6;
            checkbox[] check = new checkbox[num];
            thickness th = new thickness();
            th.bottom = 10;
            th.left = 10;
            th.right = 10;
            th.top = 10;
            for (int i = 0; i < check.length; i++)
            {
                check[i] = new checkbox();
                //设置checkbox属性
                check[i].margin = th;
                check[i].content = i + 1;
                check[i].name = "heheda";
                check[i].datacontext = "asdas";
                check[i].style = (style)this.findresource("checkboxswitchstyle");
          this.addcheckbox.children.add(check[i]);
            }
        }

 启动页面我们可以发现引入成功了。

WPF 动态添加控件以及样式字典的引用(Style introduction)

 不难发现,看一下代码,我们如何还想写别的样式,这个时候应该怎么办?难道还要往app.xaml里写?这就非常恶心了,所以我们采用引入的方式,这和css有点像!新建一个资源字典。

WPF 动态添加控件以及样式字典的引用(Style introduction)

在其中写入写入以下样式。

<resourcedictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:wpfapplication1">
    <style x:key="btninfostyle" targettype="button">
        <setter property="width" value="70"/>
        <setter property="height" value="25"/>
        <setter property="foreground" value="white"/>
        <setter property="borderthickness" value="0"/>
        <setter property="background" value="#43a9c7"/>
        <setter property="template">
            <setter.value>
                <controltemplate targettype="button">
                    <border x:name="border" background="{templatebinding background}" borderbrush="{templatebinding borderbrush}" borderthickness="{templatebinding borderthickness}" snapstodevicepixels="true">
                        <textblock text="{templatebinding content}" foreground="{templatebinding foreground}" verticalalignment="center" horizontalalignment="center"/>
                    </border>
                    <controltemplate.triggers>
                        <trigger property="ismouseover" value="true">
                            <setter targetname="border" property="background" value="#2f96b4"/>
                        </trigger>
                        <trigger property="ispressed" value="true">
                            <setter targetname="border" property="background" value="#2a89a4"/>
                        </trigger>
                    </controltemplate.triggers>
                </controltemplate>
            </setter.value>
        </setter>
    </style>
</resourcedictionary>

然后在app.xaml中进行引用,这里需要注意是,有可能我们的style和外部字典都放进去了,它们的关系是style其实也是一个字典,然后就变成了这样。

<application.resources>
        <resourcedictionary>
            <resourcedictionary.mergeddictionaries>
                <resourcedictionary source="dictionary1.xaml"/>
            </resourcedictionary.mergeddictionaries>
            <style x:key="checkboxswitchstyle" targettype="checkbox">
                <setter property="ischecked" value="false"/>
                <setter property="cursor" value="hand"/>
                <setter property="fontfamily" value="/mestoolintegration;component/fonts/#iconfont"/>
                <setter property="background" value="#ffffff"/>
                <setter property="template">
                    <setter.value>
                        <controltemplate targettype="checkbox">
                            <border width="54" name="checktruebg" height="22" borderthickness="1" background="#ffffff"  cornerradius="10" borderbrush="#acacac" >
                                <grid>
                                    <border borderthickness="1" background="#acacac" x:name="border" width="20" height="20" cornerradius="9" verticalalignment="center" horizontalalignment="left" margin="0"  >
                                        <border.rendertransform>
                                            <translatetransform  x="1"/>
                                        </border.rendertransform>
                                    </border>
                                    <textblock x:name="txt" text="{templatebinding content}" fontfamily="iconfont"  fontsize="{templatebinding fontsize}" margin="6.996,2.798,0,2.798" verticalalignment="stretch" foreground="#acacac" horizontalalignment="left" >
                                        <textblock.rendertransform>
                                            <translatetransform   x="17"></translatetransform>
                                        </textblock.rendertransform>
                                    </textblock>
                                </grid>
                            </border>
                            <controltemplate.triggers>
                                <trigger property="ischecked" value="true">
                                    <setter property="background" targetname="checktruebg"  value="#5fb878"/>
                                    <setter property="foreground" targetname="txt"  value="#ffffff"/>
                                    <setter property="background" targetname="border"  value="#ffffff"/>
                                    <setter property="text" targetname="txt" value="{binding tag,relativesource={relativesource templatedparent}}"/>
                                    <trigger.enteractions>
                                        <beginstoryboard>
                                            <storyboard>
                                                <doubleanimation storyboard.targetname="border" storyboard.targetproperty="(uielement.rendertransform).(translatetransform.x)" to="32" duration="00:00:0.2"/>
                                                <doubleanimation storyboard.targetname="txt" storyboard.targetproperty="(uielement.rendertransform).(translatetransform.x)" to="0" duration="00:00:0.2"/>
                                            </storyboard>
                                        </beginstoryboard>
                                    </trigger.enteractions>
                                    <trigger.exitactions>
                                        <beginstoryboard>
                                            <storyboard>
                                                <doubleanimation storyboard.targetname="border" storyboard.targetproperty="(uielement.rendertransform).(translatetransform.x)" to="0" duration="00:00:0.2"/>
                                                <doubleanimation storyboard.targetname="txt" storyboard.targetproperty="(uielement.rendertransform).(translatetransform.x)" to="17" duration="00:00:0.2"/>
                                            </storyboard>
                                        </beginstoryboard>
                                    </trigger.exitactions>
                                </trigger>
                                <trigger property="ischecked" value="false">
                                    <setter property="text" targetname="txt" value="{binding content,relativesource={relativesource templatedparent}}"/>
                                </trigger>
                            </controltemplate.triggers>
                        </controltemplate>
                    </setter.value>
                </setter>
            </style>
        </resourcedictionary>
    </application.resources>

我把缩进的截图发上来,更直观。

WPF 动态添加控件以及样式字典的引用(Style introduction)

 在其中还有内嵌的样式,可以这么写,如果是page的话你就 <page.resources> ,如果是windows的话那就wndows,当然如果需要页面引入字典的话你可以这么做。

<window.resources>
        <resourcedictionary>
            <resourcedictionary.mergeddictionaries>
                <resourcedictionary source="style/test.xaml"/>
            </resourcedictionary.mergeddictionaries>
        </resourcedictionary>
    </window.resources>

那么今天就这样~