WPF界面设计技巧(8)—自制山寨版CheckListBox

原文:WPF界面设计技巧(8)—自制山寨版CheckListBox
 

 

近年来IT市场山寨横行啊,我们今天也来发扬一下山寨精神,搞个自制的CheckListBox出来。

 

喏,CheckListBox 就是下面这玩意啦:

 

 

 

为什么要搞它?我们是山寨耶,说搞谁就搞谁!

 

我也不知道为什么,WPF里没有提供 CheckListBox 控件,但凭借WPF强大的外观定制能力,我们可以轻松的创制一个自己的 CheckListBox 。

 

CheckListBox 的基本功能其实和 ListBox 没有太大出入,只要将普通的ListBox 的选择模式设为多选,它就能基本实现 CheckListBox 的功用了,只不过从用户角度来说,它的使用方式不如 CheckListBox 看起来那么明确而已。

 

我们接下来就仅仅采用外观修改的方法,将 ListBox 与 CheckBox 拼插,打造出无敌山寨版 CheckListBox 。

 

首先在窗体设计器中建立一个ListBox,并为之填入一些内容项:

 

 

 

然后我们把第四讲时的列表样式代码COPY到App.xaml里去:

 

 

Code
         <!--ListBox样式-->
        <Style TargetType="ListBox">
            <Setter Property="BorderBrush" Value="#BDD4F1"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Background" Value="#F8F7F5"/>
            <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/>
            <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
            <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
        </Style>
        <!--ListBoxItem样式-->
        <Style TargetType="ListBoxItem">
            <Setter Property="Foreground" Value="#B5BABF"/>
            <Setter Property="OverridesDefaultStyle" Value="True"/>
            <Setter Property="Height" Value="24"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <Border Name="back" BorderBrush="#F8F7F5" BorderThickness="0,1,0,1">
                            <Border.Background>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                    <GradientBrush.GradientStops>
                                        <GradientStopCollection>
                                            <GradientStop Color="#F8F7F5" Offset="0.0"/>
                                            <GradientStop Color="#F8F7F5" Offset="0.5"/>
                                            <GradientStop Color="#F8F7F5" Offset="0.51"/>
                                            <GradientStop Color="#F8F7F5" Offset="1"/>
                                        </GradientStopCollection>
                                    </GradientBrush.GradientStops>
                                </LinearGradientBrush>
                            </Border.Background>
                            <ContentPresenter Margin="2" VerticalAlignment="Center"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <DoubleAnimation To="32" Duration="0:0:0.3" Storyboard.TargetProperty="Height"/>
                                            <ColorAnimation To="#F3C37C" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" />
                                            <ColorAnimation To="#952B00" Duration="0:0:0.2" Storyboard.TargetProperty="(ListBoxItem.Foreground).(SolidColorBrush.Color)" />
                                            <ColorAnimation To="#FFF" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" />
                                            <ColorAnimation To="#FFEF99" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" />
                                            <ColorAnimation To="#FFE13F" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[2].(GradientStop.Color)" />
                                            <ColorAnimation To="#FFF3B0" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[3].(GradientStop.Color)" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <DoubleAnimation BeginTime="0:0:0.4" Duration="0:0:0.2" Storyboard.TargetProperty="Height"/>
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" />
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetProperty="(ListBoxItem.Foreground).(SolidColorBrush.Color)" />
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" />
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" />
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[2].(GradientStop.Color)" />
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[3].(GradientStop.Color)" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.ExitActions>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation To="#D8E6F5" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" />
                                            <ColorAnimation To="#617A98" Duration="0:0:0.2" Storyboard.TargetProperty="(ListBoxItem.Foreground).(SolidColorBrush.Color)" />
                                            <ColorAnimation To="#F6F9FD" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" />
                                            <ColorAnimation To="#E0EBF7" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" />
                                            <ColorAnimation To="#D7E5F6" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[2].(GradientStop.Color)" />
                                            <ColorAnimation To="#F6F9FD" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[3].(GradientStop.Color)" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" />
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetProperty="(ListBoxItem.Foreground).(SolidColorBrush.Color)" />
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" />
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" />
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[2].(GradientStop.Color)" />
                                            <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[3].(GradientStop.Color)" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.ExitActions>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

 

修改 ContentPresenter 元素处的代码,用一个 CheckBox 将其包起来:

 

 

 

 

 

<CheckBox Margin="2,0,0,0" VerticalAlignment="Center" IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent},Path=IsSelected,Mode=TwoWay}">
  <ContentPresenter Margin="2"/>
</CheckBox>

 

 

从上面的代码我们可以看到,CheckBox 的 IsChecked 属性双向绑定到了列表项的 IsSelected 属性上,这时勾选 CheckBox 就会使列表项被选中,反之亦然,这就是模拟 CheckListBox 的技术核心所在。

 

现在我们的界面是这个样子了:

 

 

 

再完成最后一步,修改 ListBox 的选取模式为多选:

 

 

 

OK,运行一下就是这样了:

 

 

 

简直和真的一样!

 

如何通过代码获取选定的项呢?这样就可以了:listBox1.SelectedItems

 

再附送一个小经验:当你程序运行后,在窗体的“Initialized”事件中自动从配置文件读取到数据,并将之绑定到 ListBox 后,想要将其默认设为全选的话,应当在窗体的“ContentRendered”事件中执行全选命令“listBox1.SelectAll()”,在“Loaded”、“Initialized”等事件中执行均无效,推测可能是控件载入到绑定数据之间会存在一定延迟。

 

最后是广告:本大寨主征押寨夫人数名,名额无限,先到为大。

 

源代码下载

时间: 2024-10-31 19:12:53

WPF界面设计技巧(8)—自制山寨版CheckListBox的相关文章

WPF界面设计技巧(3)—实现不规则动画按钮

原文:WPF界面设计技巧(3)-实现不规则动画按钮    发布了定义WPF按钮的教程后,有朋友问能否实现不规则形状的按钮,今天我们就来讲一下不规则按钮的制作.   不规则按钮的做法实际上和先前我们做不规则窗体的方法差不多,只是为按钮弄个不是那么方方正正的背景而已.   我们这次沿用自定义窗体时的设计图形,设计一个动态的不规则按钮,在这个示例中我们要将先前设计的整个图形作为按钮,并让外围的圆环始终围绕中心圆形旋转,在鼠标移入时,还要产生颜色变化及发光效果.   首先用 Microsoft Expr

WPF界面设计技巧(2)—自定义漂亮的按钮样式

原文:WPF界面设计技巧(2)-自定义漂亮的按钮样式  上次做了个很酷的不规则窗体,这次我们来弄点好看的按钮出来,此次将采用纯代码来设计按钮样式,不需要 Microsoft Expression Design 辅助了.   首先打开 Microsoft Visual Studio 2008 ,新建一个WPF项目,在上面随便放几个按钮:     然后给各个按钮设置不同的背景颜色:     设置好之后就是这样啦:     然后我们就开始在 App.xaml 文件中定义按钮样式了:     定义的样式

WPF界面设计技巧(1)—不规则窗体图文指南

原文:WPF界面设计技巧(1)-不规则窗体图文指南  初到园子,奉上第一篇入门级教程,请勿见笑. 以往WinForm编程中,实现不规则窗体是有一定难度的,更难的是不规则窗体的边缘抗锯齿及局部透明处理.而现在,WPF的出现使这个问题迎刃而解,使得我们可以轻松.灵活地美化用户界面. 下面就让我们来看看如何实现一个不规则窗体: 首先我们需要借助Microsoft Expression Design 2来进行图形设计.(这里使用Photoshop等传统软件也可以,但是只能利用PNG格式来实现透明,其缺点

WPF界面设计技巧(11)-认知流文档 &amp; 小议WPF的野心

原文:WPF界面设计技巧(11)-认知流文档 & 小议WPF的野心     流文档是WPF中的一种独特的文档承载格式,它的书写和呈现方式都很像HTML,它也几乎具备了HTML的绝大多数优势,并提供了更强的编程支持及对WPF其他元素的兼容.   直接来看代码吧,需要讲解的地方比较多,我就直接注释在代码里了,看起来更方便些:     Code<Window x:Class="流文档.Window1"     xmlns="http://schemas.microso

WPF界面设计技巧(10)-样式的继承

原文:WPF界面设计技巧(10)-样式的继承     PS:现在我的MailMail完工了,进入内测阶段了,终于可以腾出手来写写教程了哈,关于MailMail的介绍及内测程序索取:http://www.cnblogs.com/SkyD/archive/2008/08/09/1264083.html  欢迎帮我捉虫,以及与我交流WPF技术   WPF的样式的继承属性极少被文章提及,以至于我在编写MailMail期间为此踌躇数日,最后终于在E文版的MS社区得到指点才得以解惑.   现将其分享出来,这

WPF界面设计技巧(4)—自定义列表项样式

原文:WPF界面设计技巧(4)-自定义列表项样式   有前面修改按钮样式的基础,我们可以尝试来定制一个即好看又好用的 ListBox ,今天先来讲"好看"部分.   打开 Microsoft Visual Studio 2008 ,建立一个WPF应用程序,调整窗体大小,在窗体内创建一个 ListBox 和一个 Button ,按下图所示布局.   在  Window1.xaml 中为窗体 Loaded 事件及按钮 Click 事件添加事件处理:       Code<Window

WPF界面设计技巧(7)—模拟电梯升降的缓动动画

原文:WPF界面设计技巧(7)-模拟电梯升降的缓动动画     如同Flash一样,WPF的亮点之一也在于其擅于表现平滑的动画效果,但以移动动画来说,仅凭简单的起始位置.目标位置,所产生的动画仍会非常生硬,这种动画忽略了移动开始时的加速过程与移动结束时的减速过程.   WPF在关键帧动画中提供了样条内插(Spline)型的关键帧,用以控制变化的速率曲线,但这东西实在有些复杂,且不够形象化,我研究很久也没明白如何实现"缓入--缓出"的效果,随后我从一本经典牛X却鲜有人知的过时的Flash

WPF界面设计技巧(5)—自定义列表项呈现内容

原文:WPF界面设计技巧(5)-自定义列表项呈现内容    接续上次的程序,稍微改动一下原有样式,并添加一个数据模板,我们就可以达成下面这样的显示功能:     鼠标悬停于文件列表项上,会在工具提示中显示图像缩略图及文件名.文件大小信息.   选中一个列表项,该列表项会扩大,并动态显示出一个小缩略图及文件的所在路径.   代码如下:   Code<Application x:Class="自定义列表项.App"    xmlns="http://schemas.micr

WPF界面设计技巧(9)—使用UI自动化布局

原文:WPF界面设计技巧(9)-使用UI自动化布局    最近一直没时间更新这系列文章,因为我一直在埋头编写我的第一个WPF应用程序:MailMail   今天开始编写附属的加密/解密工具,对UI自动化布局有些心得,就此分享出来.   我们先来看一下实现的效果:       这样的界面是怎么个自动法呢?请看下图:       就是说界面在适度的伸缩时,不会破坏其布局结构及美观性.   这样做有什么好处呢?你可以想象以下情况:   1.需要用户或通过程序控制变更窗体尺寸以适应特殊要求时.UI自动化