能否编程创建并呈现XAML控件?UWP脱离页面独立渲染可行吗?
UWP中编程创建并渲染XAML控件的问题解答
咱们先直接回应你的两个问题:
- 问题1:当然可以以编程方式创建并呈现XAML控件!在UWP开发里,动态生成控件是非常常见的操作,比如根据后端数据生成列表项、动态构建弹窗内容等等。
- 问题2:没办法脱离可视化树独立渲染UI控件——这正是你测试代码抛出
System.ArgumentException: 值不在预期范围内的根本原因。
你的测试代码哪里出问题了?
你创建了TextBox并设置了文本,但这个控件从来没有被加入到可视化树中,也没有经过布局系统的测量(Measure)和排列(Arrange)步骤。RenderTargetBitmap.RenderAsync这个方法有个硬性要求:目标控件必须处于已加载(Loaded)状态,也就是要有有效的布局尺寸,并且属于可视化树的一部分,否则就会因为无法获取控件的渲染上下文而抛出异常。
修正后的测试代码示例
下面是调整后的代码,核心是给控件一个临时的父容器,并且手动触发布局流程,让控件进入可渲染状态:
[TestMethod] public async Task TestWebView() { var taskSource = new TaskCompletionSource<object>(); await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( CoreDispatcherPriority.Normal, async () => { try { var text = new TextBox(); text.Text = "hello"; // 给TextBox找个临时“家”,加入可视化树 var tempContainer = new Grid(); tempContainer.Children.Add(text); // 手动触发布局测量,确保控件有明确的尺寸 tempContainer.Measure(new Size(200, 50)); tempContainer.Arrange(new Rect(0, 0, 200, 50)); var renderer = new RenderTargetBitmap(); // 可以渲染整个容器,或者直接渲染TextBox(此时它已经有有效尺寸了) await renderer.RenderAsync(tempContainer); // await renderer.RenderAsync(text); // 这行现在也能正常执行了 } catch (Exception e) { taskSource.SetException(e); } }); await taskSource.Task; }
额外说明
- 如果你的测试只是想验证控件的属性是否设置正确(比如
TextBox.Text是不是"hello"),其实完全不需要渲染,直接断言text.Text == "hello"就足够了,能省不少事。 - 要是必须测试渲染逻辑,除了上面的临时容器方法,你也可以把控件添加到当前页面的可视化树中(比如隐藏的容器里),完成渲染后再移除,效果是一样的。
内容的提问来源于stack exchange,提问作者Johnny Haddock
相关产品推荐
相关产品推荐

