鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > .net技术 > WinRT/Metro > >

从WPF到Silverlight到WinRT: 自定义控件从此没有Visual和OnRende

来源:互联网 作者:佚名 时间:2012-11-11 22:55
目录 这个话题早就想写写了,一直没时间,后来索性忘了,今天在写WP7控件又遇到类似话题,把他写出来。 注意: 由于WinRT的XAML衍生自Silverlight,两者XAML相关类型的执行虽有差异,但整体相似,不影响本文话题,因此将Silverlight和WinRT合并起来说,并以W

目录

 

这个话题早就想写写了,一直没时间,后来索性忘了,今天在写WP7控件又遇到类似话题,把他写出来。

 

注意:

由于WinRT的XAML衍生自Silverlight,两者XAML相关类型的执行虽有差异,但整体相似,不影响本文话题,美国服务器,因此将Silverlight和WinRT合并起来说,并以WinRT代码做示例。

 

 

更精简的UIElement继承树

在WPF中,UIElement上是Visual –> DependencyObject –> DispatcherObject –> Object

 

没有了Visual和DispatcherObject。

 

首先在Silverlight/WinRT中,DispatcherObject被整合到了DependencyObject中了,这个DispatcherObject的Dispatcher属性返回一个Dispatcher对象,同时CheckAccess和VerifyAccess方法其实就是调用Dispatcher对象的相应方法。那么在Silverlight和WinRT中,只需要DependencyObject返回一个Dispatcher就可以了。(在Silverlight中Dispatcher只有CheckAccess方法。在WinRT中,该类型的名称是CoreDispatcher,在Windows.UI.Core命名空间内,它有一个HasThreadAccess属性有类似的功能)

 

接下来就是少了Visual,也是本文的主题。下面将更具体的阐述Visual的离去所带来的影响。

 

 

 

WPF中使用VisualCollection来自定义控件

WPF中可以使用VisualCollection来自定义控件直接在代码中控制Visual Tree的数据,VisualCollection的初始化需要另一个Visual对象,创建好VisualCollection后,该集合的改变将同时改变目标控件的Visual Tree数据,同时还有一个UIElementCollection,不仅会改变Visual Tree,同时还会改变Logical Tree的数据。更多可以参考我的另一篇文章:

WPF中神奇的容器:VisualCollection,UIElementCollection和ItemCollection

 

对于自定义控件,同时还需改写Visual.GetVisualChild方法和Visual.VisualChildrenCount属性,把需要返回的值和VisualCollection联系起来。这样WPF系统可以正确获取Visual Tree中数据的信息。

最后则是通过改写MeasureOverride和ArrangeOverride方法来把Visual Tree中的数据正确显示出来(相关可以参考:WPF:为什么需要Measure和Arrange两步?)。

 

那么我们自定义一个非常简单的控件,一个只显示一个Button的控件,如下WPF代码:

 

 

 

运行后,同样会有一个叫Mgen的Button出现在屏幕上:

image

 

当然,上面的这一切WPF早就支持了,只不过WPF还提供更多的选择!VisualCollection还有OnRender都可以。OnRender后面会说,当然最传统的方式还是上述这种方式的,这个在WPF/Silverlight/WinRT中都是被很好地支持的,服务器空间,可以说是XAML的标准创建自定义控件方法吧。当然对于Silverlight/WinRT这种对性能和大小都必须要求更高的框架,把一些可有可无的东西剪掉也是在情理之中的。

对于WPF的这种创建控件方法,跟上方类似,可以参考这篇专门为WPF写的文章:

WPF:详解创建Lookless自定义控件——文件选择控件

 

 

 

最后的OnRender方法

WPF还有一种Silverlight和WinRT都没有的自定义控件方法,那就是UIElement的OnRender方法。这种方法的存在或多或少是保留另一个早期UI框架Windows Forms的方式。也就是Windows Forms中经典的Control.OnPaint方法。OnRender和OnPaint完全类似,香港空间,DrawingContext对象就相当于Windows Forms中的Graphics对象,这种经典的绘图和刷新机制的控件显示完全可以追溯到更原始的Win32 API控件的创建。

 

当然,由于OnRender方法实在是太底层了,因此无法绘制任何可交互的控件(把它想象成画图),因此一般除了从底层创建控件或者做一些对性能要求较高控件你是很少需要他的。

 

这里,通过FormattedText和DrawText方法来创建一个最简单的显示文字的控件,注意依赖属性的定义需要加入FrameworkPropertyMetadataOptions.AffectsRender选项来触发OnRender。

代码:

 

 

结果:

网友评论
<