silverlight自定义控件之ProgressBar
2009-09-27 16:50 chameleon 阅读(1482) 评论(1) 收藏 举报
silverlight的控件库本身提供了progressbar的支持,但是不能显示进度的文本,有时候又有这种需求。当然可以自己再加一个TextBlock,来监听ValueChanged事件在里面设置TextBlock的文本。我用Reflector查看了一下默认的progressbar的实现,自己写了一个。基本功能可以用,BUG未知。
代码如下:
controltemplate cs
Code
这么用
谈谈遇到的问题:
代码如下:
<my:ProgressBar Height="30" Maximum="100" Minimum="0" Value="40" Background="AliceBlue"></my:ProgressBar>
谈谈遇到的问题:
- OnApplyTemplate()这个函数的触发时间感觉不大对劲,为何在属性都初始化完毕了以后该函数才会触发呢?一般的思维不应该是呈现出控件再来修改其属性值么?不过这问题似乎不少人在讨论。拿我这个控件为例,OnValueChanged事件激发的时候,由于OnApplyTemplate()还未运行,导致this._root、this._rect等为null,所以在SetProgressBarLength()函数里这两个变量都是null的。但是该控件的Value和Text可能已经被赋值了(如果你在XAML里赋值了的话)。所以我不得不在OnApplyTemplate()内部重新判断并赋值。
- 最初我的OnValueChanged()被执行了两次,由于该方法是override的方法,所以我怀疑是RangeBase里面出了问题。但是发现这是由于XAML里面没有设置Maximum和Minimum引起的,RangeBase会给他赋一次初始值。所以别管用原来的ProgressBar还是我写的这个ProgressBar,指定Maximum和Minimum都是必须的。
- 我这个控件的树结构是Border->Grid->(Rectangle,TextBlock),Border用来现在边框,Grid用来盛放进度条和文本,主要是放到Grid内有叠加的效果,而且居中比较好控制。Rectangle用来显示进度条,TextBlock用来显示进度的文本信息。这样主要的工作就是根据控件的Value值计算Rectangle的宽度,同样遇到了问题。最初我用的是_rect的ActualWidth,发现无论如何这个值总是0.0d。于是改用Width,Width属性是个get;set;属性,也就是他的返回值是你在XAML里设置的值,当我在XAML里显式的设置了这个值,我的控件运行良好。但是有时候我们不需要设置这个值啊,比如我把我的控件放到StackPanel里面,他自动适应了。虽然这时候控件是有宽度的,但是他的Width值却是是NAN,因为木设置嘛。而ActualWidth是个get;属性,你能获取控件当前的实际值。一番DEBUG之后,又重新使用ActualWidth来计算,结果又遇到问题,初次载入时,在OnApplyTemplate()最后面的几行,最初是这样的:
1但是在SetProgressBarLength()我的_rect的ActualWidth的值总是0.0d。后来查看ProgressBar的源代码发现它用到了了一个SizeChanged事件,就是给this._root注册一个SizeChanged事件,一旦控件的根节点的高宽发生了变化,就去修改内部_rect的宽度。而实际上_root_SizeChanged这个回调函数就被使用了一回,其他执行SetProgressBarLength()都是在OnValueChanged中实现的。到此我发现遇到的问题和OnApplyTemplate()关系比较大,难道就不能在完全把控件树呈现完毕后再给之中的属性赋值么?
if (this._rect != null)
2
this.SetProgressBarLength(); - 还是OnApplyTemplate()函数,这个函数内只有两句。最初是base.OnValueChanged(oldValue, newValue)在前的,后来发现this.SetProgressBarLength()内我把文本的内容写死了,而有时候不一定非得显示百分比,也许需要value/maxe的形式,所以我就把base.OnValueChanged(oldValue, newValue)放后面了,默认显示百分比,如果想显示自己的格式,就注册ValueChanged事件,在里面设置Text属性即可。
- 关于几个属性的绑定:我把控件的Background绑定到_root的Background上了,Foreground绑定到_rect的Fill上了,FontFamily和FontSize绑到_txtProgress上了,结果发现_txtProgress的文本颜色木属性能绑定了。。。但这个倒是好弄,自己再添加一个依赖属性即可。在搞这个绑定的过程中同样遇到一个问题,就是我把控件的Foreground设置了以后,最初木有设置_txtProgress的Foreground,结果当我的Value足够大了以后(大于70%),由于silverlight里面的字体属性会自动继承,结果文本和进度条颜色一样了,反映到效果上就是文本消失了,为此我怔了很长时间,最后才恍然大悟。



}
}
浙公网安备 33010602011771号