Подтвердить что ты не робот

Принудительное рендеринг элемента управления WPF в памяти

У меня есть следующий код:

void Test()
{
    currentImage.Source = GetBitmap();
    RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96.0, 96.0, PixelFormats.Default);
    rtb.Render(currentImage);
}

Этот код должен отображать currentImage, который является элементом управления Image в моем xaml, в RenderTargetBitmap.

Это не работает, rtb возвращает пустое изображение, проблема в currentImage еще не проявила себя, и поэтому такое поведение ожидается, я думаю...

Чтобы обойти эту проблему, я написал этот код:

void Test()
{
    currentImage.Source = GetBitmap();

    this.Dispatcher.BeginInvoke((Action)delegate()
    {
        RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96.0, 96.0, PixelFormats.Default);
        rtb.Render(currentImage);
    }, System.Windows.Threading.DispatcherPriority.Render, null);

}

В принципе, я жду, пока currentImage будет визуализирован, и затем я смогу его правильно отобразить в RenderTargetBitmap.

Есть ли способ заставить его работать без использования этого обходного пути? Заставить элемент управления Image для рендеринга в памяти?

спасибо!

4b9b3361

Ответ 1

использовать ViewBox для рендеринга в памяти

Grid grid = new System.Windows.Controls.Grid() { Background = Brushes.Blue, Width = 200, Height = 200 };
Viewbox viewbox = new Viewbox();
viewbox.Child = grid; //control to render
viewbox.Measure(new System.Windows.Size(200, 200));
viewbox.Arrange(new Rect(0, 0, 200, 200));
viewbox.UpdateLayout();
RenderTargetBitmap render = new RenderTargetBitmap(200, 200, 150, 150, PixelFormats.Pbgra32);
render.Render(viewbox);

Ответ 2

Я думаю, что это ЛУЧШИЙ ответ.
viewbox работал не так, как ожидалось, и это оказалось ненужным накладным.

Вот копия этого ответа (вместо простой ссылки)


Вам нужно принудительно выполнить рендеринг элемента или дождаться, пока объект будет визуализирован. Затем вы можете использовать свойства ActualHeight и ActualWidth.

Чтобы заставить рендер:

  MenuItem item = new MenuItem();
  item.Header = "bling";
  item.Icon = someIcon;
  //Force render
  item.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
  item.Arrange(new Rect(item.DesiredSize));

В этом примере MenuItem не была указана явная высота или ширина. Тем не менее, принудительное рендеринг отобразит его, принимая во внимание текст и значок заголовка.