【问题标题】:render WPF user control in memory, not on screen在内存中呈现 WPF 用户控件,而不是在屏幕上
【发布时间】:2016-05-12 10:02:25
【问题描述】:

我有一个复杂的用户控件,它显示图像并在其上方用阴影和东西覆盖某些标签。我想在内存中渲染所有这些东西,然后制作这张地图的图像,然后在真实的用户界面中使用这张图像。这就是事情最终的样子。

我这样做是因为界面开始随着所有这些元素缓慢移动,我正在尝试简化它。我走的路对吗??

这里的问题是我创建了brainMap,向它提供数据,然后尝试创建imagen 和BAM!无法完成,因为没有渲染整个组件,ActualWith 为零。

这就是我从控件中提取图像的方式(当控件呈现在屏幕中时,该方法非常有效)

    /// <summary>
    /// The controls need actual size, If they are not render an "UpdateLayout()" might be needed.
    /// </summary>
    /// <param name="control"></param>
    /// <param name="Container"></param>
    public static System.Windows.Controls.Image fromControlToImage(System.Windows.FrameworkElement control)
    {
        if (control.ActualWidth == 0)
            throw new Exception("The control has no size, UpdateLayout is needed");
     // Here is where I get fired if the control was not actually rendered in the screen

        RenderTargetBitmap rtb = new RenderTargetBitmap((int)control.ActualWidth, (int)control.ActualHeight, 96, 96, PixelFormats.Pbgra32);
        rtb.Render(control);

        var bitmapImage = new BitmapImage();
        var bitmapEncoder = new PngBitmapEncoder();
        bitmapEncoder.Frames.Add(BitmapFrame.Create(rtb));

        using (var stream = new System.IO.MemoryStream())
        {
            bitmapEncoder.Save(stream);
            stream.Seek(0, System.IO.SeekOrigin.Begin);

            bitmapImage.BeginInit();
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.StreamSource = stream;
            bitmapImage.EndInit();
        }
        System.Windows.Controls.Image testImage = new System.Windows.Controls.Image();
        testImage.Source = bitmapImage;
        return testImage;
    }

如果控件一开始是布局的一部分,添加 UpdateLayout 确实可以解决问题(这就是为什么我在那里为自己添加了一个异常)但是当控件是从代码创建并且从未到达页面时 UpdateLayout 不会完全有帮助。

如何确保内存中所有元素的渲染,然后在不进入页面的情况下渲染它的图像? (固定尺寸是可以接受的)

【问题讨论】:

  • 需要成为可视化树的一部分才能呈现,因为控件的呈现方式(至少 ActualWidth/Height 明智)取决于相同的视觉树。我记得曾经遇到过类似的问题,但忘记了我最终是否或如何解决它。虽然我有这种我没有的唠叨感,但我专注于让实际控制​​的性能可以接受,而不是继续进行艰苦的战斗。

标签: c# wpf


【解决方案1】:

在你的情况下,解决方案是这样的:

 public static System.Windows.Controls.Image fromControlToImage(System.Windows.FrameworkElement control)
 {
    Size size = new Size(100, 100); // Or what ever size you want...
    control.Measure(size);
    control.Arrange(new Rect(size));
    control.UpdateLayout();
    ...
 }

在内存中渲染 WPF经常被问到在 SO:

Drawing Control to Memory

由于控件没有父容器,您需要调用 Measure 和 Arrange 才能进行适当的布局。

WPF Get Size of UIElement in Memory

您需要强制渲染该项目,或等待该项目被渲染。然后,您可以使用 ActualHeight 和 ActualWidth 属性。

为您的目的附加:

Force Rendering of a WPF Control in Memory

或许你可以使用 ViewBox 在内存中渲染

【讨论】:

  • 嘿,想象一下,当时肯定有不同的问题,这些天我用 WPF 做的太少了。一个起来。
  • @WillemvanRumpt 感谢 SO 和 Google ;)
猜你喜欢
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
  • 2022-10-24
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
  • 2019-06-30
相关资源
最近更新 更多