WPF的逻辑树与视觉树(3)Visual呈现
2010-08-07 01:33 Clingingboy 阅读(3526) 评论(1) 编辑 收藏 举报这篇就点到为止,挑重点讲
绘图方式有两种
1.继承UIElement,重写OnRender方法
public partial class Window5 : Window { public Window5() { InitializeComponent(); this.Content = new RectangleElement(); } } public class RectangleElement : UIElement { protected override void OnRender(DrawingContext drawingContext) { drawingContext.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 20)); base.OnRender(drawingContext); } }
2.DrawingVisual 轻量级绘图,只提供显示和测试点击功能,DrawingVisual继承自ContainerVisual,所以其也是Visual集合容器
public class RectangleElement : UIElement { DrawingVisual visual; public RectangleElement() { visual = new DrawingVisual(); var drawingContext = visual.RenderOpen(); drawingContext.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 20)); drawingContext.Close(); this.AddVisualChild(visual); } protected override Visual GetVisualChild(int index) { return visual; } protected override int VisualChildrenCount { get { return 1; } } }
DrawingVisual无法单独存在,必须放在一个容器中(需要有布局系统)呈现.我们看到每次添加一个Visual的时候,总还是难免要实现GetVisualChild和VisualChildrenCount这两个成员.除了ContainerVisual这些轻量级的对象,Panel会帮我们做掉上面这些工作.但基类却变成了UIElement.事实上当添加Visual以后,同时还要计算布局的尺寸,所以有必要的话,可以对UIElement或者FrameworkElement重写以上两个成员。因为有时候我们只需要一次布局和添加多个Visual,以提升性能
重写默认窗体的视觉树
public partial class Window5 : Window { DrawingVisual dv; public Window5() { InitializeComponent(); dv = new DrawingVisual(); } protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) { var drawingContext = dv.RenderOpen(); drawingContext.DrawRectangle(Brushes.Red, null, new Rect(0, 0, this.ActualWidth, ActualHeight)); drawingContext.Close(); base.OnRenderSizeChanged(sizeInfo); } protected override Visual GetVisualChild(int index) { return dv; } }重写后的窗体视觉树达到了最小化

上面看到并没有调用AddVisualChild方法,而视觉树的判断依据还是根据GetVisualChild和VisualChildrenCount,不过还是乖乖地加上AddVisualChild方法以免出现什么问题.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现