WPF自定义ListBox(二)

Helloj2ee的自定义ListBox(一),虽然很用心,但看出来反响不强烈。只能这一篇再给力一点。虽然评论很少,但是也看出一些讯息。

讯息之一,就是Helloj2eeWPF看不懂。的确在这里写的不是基本的东西,而是对其WPF的相关基础概念掌握了之后,才能看的一个系列。自定义控件在《葵花宝典——WPF自学手册》一书中,是放到第六卷——华山之巅,足见其高阶。因此Helloj2ee在后面列出的参考文献,就很有价值了。因为您若是看不懂,不妨去参考相关文献,即便您没有葵花宝典一书,但总可以知道需要掌握的相关概念是什么,参阅其他书又何妨?

讯息之二,是提供的源码无法打开,那么Helloj2ee已经更新过。如果解压还是失败,您不妨在下面的回帖中告诉我。

说到给力,那么只有让这个控件在本章当中酷起来或者炫起来,才是给力的王道。

 

CircularPanel的布局之美

 

给力之前,Helloj2ee还是得枯燥一下,CircularPanel的那几个参数。第一个参数是CircularPanel的初始角度(InitialAngle)。

 

 

剩下的参数在该图中可以展现。Align属性实质是指的ListBoxItem的旋转点,Left表示外接矩形的左上角点,Center表示外接矩形的中心点,Right表示外接矩形的右下角点。而Radius指的是从圆心到旋转点的半径。AngleItem则是ListBoxItem之间的角度差。如下图所示:

 

ListBoxItem的外观

ListBoxItem的外观也需要通过模板来自定义。注意观察下图。实际上这样一个ListBoxItem是由如下五个元素组成的,分别是一个Path,三个Rectangle和一个TextBlock组成的。可能有人要问,为什么是三个Rectangle,实际上只是为了让这个边框一层一层更有层次感。

 

好了,我们来看看代码。

 

ExpandedBlockStart.gif 代码
< Style  TargetType =" {x:Type ListBoxItem} " >
            
< Setter  Property ="Template" >
                
< Setter.Value >
                    
< ControlTemplate  TargetType =" {x:Type ListBoxItem} " >
                        
< Grid  x:Name ="gridSwatch"  Height ="180"  Background ="#00000000"  RenderTransformOrigin ="0.447,0.88"  Width ="55"  Cursor ="Hand"   >
                            
< Grid.RenderTransform >
                                
< TransformGroup >
                                    
< ScaleTransform  />
                                    
< SkewTransform />
                                    
< RotateTransform  Angle ="90" />
                                    
< TranslateTransform  X ="-65.75"  Y ="-71.05" />
                                
</ TransformGroup >
                            
</ Grid.RenderTransform >
                            
                            
< Path  x:Name ="overShape"  Data ="M0,3.0000024 C0,1.3431468 1.3431457,0 3,0 L47,0 C48.656853,0 50,1.3431468 50,3.0000024 L50,185.00012 C50,186.65698 48.656853,188.00014 47,188.00014 C30.666666,190.16705 26.666666,222.49997 24.666666,231.5 C22.833332,222.49997 14,187.83371 3,188.00014 C1.3431457,188.00014 0,186.65698 0,185.00012 z"  Fill ="#FF3C3C3C"  Stroke =" {x:Null} "  Margin ="0,-4,0,-47.5"  IsHitTestVisible ="False"  Visibility ="Collapsed" />
                            
< Rectangle  x:Name ="shadow3"  Margin ="-4,-8,-4,-8"  Fill ="#FF000000"  Stroke =" {x:Null} "  RadiusX ="7"  RadiusY ="7"  Opacity ="0.08"  IsHitTestVisible ="False" />
                            
< Rectangle  x:Name ="shadow2"  Margin ="-3,-7,-3,-7"  Fill ="#FF000000"  Stroke =" {x:Null} "  RadiusX ="6"  RadiusY ="6"  Opacity ="0.08"  IsHitTestVisible ="False" />
                            
< Rectangle  x:Name ="shadow1"  Margin ="-2,-6,-2,-6"  Fill ="#FF000000"  Stroke =" {x:Null} "  RadiusX ="5"  RadiusY ="5"  Opacity ="0.08"  IsHitTestVisible ="False" />
                            
< Rectangle  x:Name ="whiteSwatch"  Margin ="-1,-5,-1,-5"  Fill ="#FFFFFFFF"  Stroke =" {x:Null} "  RadiusX ="4"  RadiusY ="4"  IsHitTestVisible ="False" />
                            
< TextBlock   FontSize ="22"  FontFamily ="华文行楷"  Text =" {Binding XPath=ImageText} "   >
                                
< TextBlock.RenderTransform >
                                    
< TransformGroup >
                                    
< RotateTransform  Angle ="90" />
                                    
< TranslateTransform  X ="30"  Y ="30" />
                                    
</ TransformGroup >
                                    
</ TextBlock.RenderTransform >
                            
</ TextBlock >
                        
</ Grid >
                    
</ ControlTemplate >
                
</ Setter.Value >
            
</ Setter >
        
</ Style >

 

 

 

上面的代码有几处,Helloj2ee简单说明一下。

1ListBoxItem自定义的模板,首先是一个Grid面板,该面板用了好几个变换,构成了一个变换组,尽管有诸如ScaleTransform等都未填写,但是这是为后面的动画埋下伏笔。

2)这样的Path,的确难以用VS2010绘制出来,那么使用Expression Blend绘制就好,此外IsHitTestVisible属性设置为False,表明它并不接受用户的输入,只是作为一个基本的图元构成,同时设置了该Path在平时并不可见。

3)注意TextBlock通过XPath属性设置了和XML文件的绑定。

好了再次运行程序,您看到了什么?

 

即使整个ListBox已经变样,但是它选择的效果可以说极其不好,因此我们必须再接再力,给它添加上一些动画效果。添加动画的效果主要靠控件模板的Trigger来触发了。大家先看代码,然后Helloj2ee再加以解释。

 

ExpandedBlockStart.gif 代码
< ControlTemplate.Triggers >
                            
< EventTrigger  RoutedEvent ="ListBoxItem.MouseEnter" >
                                
< BeginStoryboard >
                                    
< Storyboard >
                                        
< DoubleAnimationUsingKeyFrames  BeginTime ="00:00:00"  Storyboard.TargetName ="gridSwatch"  Storyboard.TargetProperty ="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" >
                                            
< SplineDoubleKeyFrame  KeySpline ="0.5,0,0.5,1"  KeyTime ="00:00:00.1000000"  Value ="1.2" />
                                        
</ DoubleAnimationUsingKeyFrames >
                                        
< DoubleAnimationUsingKeyFrames  BeginTime ="00:00:00"  Storyboard.TargetName ="gridSwatch"  Storyboard.TargetProperty ="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" >
                                            
< SplineDoubleKeyFrame  KeySpline ="0.5,0,0.5,1"  KeyTime ="00:00:00.1000000"  Value ="1.2" />
                                        
</ DoubleAnimationUsingKeyFrames >
                                        
< ObjectAnimationUsingKeyFrames  BeginTime ="00:00:00"  Duration ="00:00:00.0010000"  Storyboard.TargetName ="overShape"  Storyboard.TargetProperty ="(UIElement.Visibility)" >
                                            
< DiscreteObjectKeyFrame  KeyTime ="00:00:00" >
                                                
< DiscreteObjectKeyFrame.Value >
                                                    
< Visibility > Visible </ Visibility >
                                                
</ DiscreteObjectKeyFrame.Value >
                                            
</ DiscreteObjectKeyFrame >
                                        
</ ObjectAnimationUsingKeyFrames >
                                    
</ Storyboard >
                                
</ BeginStoryboard >
                            
</ EventTrigger >
                            
< EventTrigger  RoutedEvent ="ListBoxItem.MouseLeave" >
                                
< BeginStoryboard >
                                    
< Storyboard >
                                        
< DoubleAnimationUsingKeyFrames  BeginTime ="00:00:00"  Storyboard.TargetName ="gridSwatch"  Storyboard.TargetProperty ="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" >
                                            
< SplineDoubleKeyFrame  KeySpline ="0.5,0,0.5,1"  KeyTime ="00:00:00.2000000"  Value ="1" />
                                        
</ DoubleAnimationUsingKeyFrames >
                                        
< DoubleAnimationUsingKeyFrames  BeginTime ="00:00:00"  Storyboard.TargetName ="gridSwatch"  Storyboard.TargetProperty ="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" >
                                            
< SplineDoubleKeyFrame  KeySpline ="0.5,0,0.5,1"  KeyTime ="00:00:00.2000000"  Value ="1" />
                                        
</ DoubleAnimationUsingKeyFrames >
                                        
< ObjectAnimationUsingKeyFrames  BeginTime ="00:00:00"  Duration ="00:00:00.0010000"  Storyboard.TargetName ="overShape"  Storyboard.TargetProperty ="(UIElement.Visibility)" >
                                            
< DiscreteObjectKeyFrame  KeyTime ="00:00:00" >
                                                
< DiscreteObjectKeyFrame.Value >
                                                    
< Visibility > Collapsed </ Visibility >
                                                
</ DiscreteObjectKeyFrame.Value >
                                            
</ DiscreteObjectKeyFrame >
                                        
</ ObjectAnimationUsingKeyFrames >
                                    
</ Storyboard >
                                
</ BeginStoryboard >
                            
</ EventTrigger >
                           
                            
< Trigger  Property ="IsMouseOver"
                         Value
="True" >
                                
< Setter  Property ="Panel.ZIndex"
                            Value
="1"   />
                            
</ Trigger >
                        
</ ControlTemplate.Triggers >

 

 

主要是在MouseEnterMouseLeave事件里做文章,当鼠标滑过某个ListBoxItem,我们通过改变它的ScaleTransform,让它变大。而离开ListBoxItem再通过改变ScaleTransform,让它恢复原状。比如像这样的语法,就未必有很多人能够写出来。请大家留心。

 

Storyboard.TargetName="gridSwatch" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"

 

 

 

光是变换还是不够的,因为当鼠标滑过的时候,很有可能希望这个ListBoxItem凸现出来,那么要用到的就是Panel.ZIndex这个附加属性,通过改变这个值,让鼠标滑过的ListBoxItem凸现出来。

好了,现在的ListBoxItem已经完全变样了,但是还有美中不足。最为美中不足的就是ListBoxItem选中的时候,会出现一个虚框,这样的视觉效果确实很不好。

 

 

解决之道,又是一句话。

 

< Setter  Property ="FocusVisualStyle"  Value =" {x:Null} "   />

 

 

 

还有美中不足,比如选中某一个ListBoxItem,我们该作如何反应呢。这里helloj2ee就不再写这样的代码了。各位去尝试一下吧。

剩下的Helloj2ee需要做的是让这个对话框透明起来和加上中间的小圆点。中间的小圆点并不难加,让对话框完全透明也So Easy。那么Helloj2ee向各位奉上代码就好了。如果真的新手不知道该如何让不规则对话框透明的话,那么不妨参见葵花宝典第88.3.4节好了。

 源代码:/Files/helloj2ee/ListBoxDemo3.rar

 

 

 

 

 

 

转载于:https://www.cnblogs.com/helloj2ee/archive/2010/12/09/1900818.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值