Вопрос

Я нашел новый поворот на вопрос «Visual to Rendertargetbitmap»!

Я предоставляю превью вещей WPF для дизайнера. Это означает, что мне нужно сделать визуальный WPF и сделать его до растрового изображения без того визуального. Получил хороший маленький метод, чтобы сделать это, как это увидеть здесь, он идет

private static BitmapSource CreateBitmapSource(FrameworkElement visual)
{
    Border b = new Border { Width = visual.Width, Height = visual.Height };
    b.BorderBrush = Brushes.Black;
    b.BorderThickness = new Thickness(1);
    b.Background = Brushes.White;
    b.Child = visual;

    b.Measure(new Size(b.Width, b.Height));
    b.Arrange(new Rect(b.DesiredSize));

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

    // intermediate step here to ensure any VisualBrushes are rendered properly
    DrawingVisual dv = new DrawingVisual();
    using (var dc = dv.RenderOpen())
    {
        var vb = new VisualBrush(b);
        dc.DrawRectangle(vb, null, new Rect(new Point(), b.DesiredSize));
    }
    rtb.Render(dv);
    return rtb;
}

Работает нормально, за исключением одной лечебной вещи ... Если у моего Frameetelement есть VisualBrush, эта щетка не заканчивается в окончательном отображенном растровом карте. Что-то вроде этого:

<UserControl.Resources>
    <VisualBrush
        x:Key="LOLgo">
        <VisualBrush.Visual>
            <!-- blah blah -->
<Grid 
    Background="{StaticResource LOLgo}">
<!-- yadda yadda -->

Все остальное отображает растровое изображение, но это VisualBrush просто не покажет. Очевидные решения Google были предприняты попытки и потерпели неудачу. Даже те, которые специфически упоминают VisualBrushes, отсутствуют от растровых изображений RTB'D.

У меня есть подлый подозритель, это может быть вызвано тем, что его ресурс, и этот ленивый ресурс не включен. Так что возможное исправление было бы как-то (???), принудительно разрешение всех статических ссылок на ресурсы перед рендерингом. Но я не имею абсолютно понятия, как это сделать.

Кто-нибудь есть исправить для этого?

Это было полезно?

Решение

У вас есть две проблемы:

  1. Вы не установили презентации на ваши визуальные настолько загруженные события, не будут стрелять.
  2. Вы не промыли очередь диспетчера. Без промывки очереди диспетчера любые функции, которые используют обратные вызовы диспетчера, не будут работать.

Непосредственная причина вашей проблемы - неспособность заподернуть очередь диспетчера, поскольку VisualBrush использует его, но вы, вероятно, столкнулись с проблемами представления с представлением до длительного времени, поэтому я исправлю оба обоих.

Вот как я это делаю:

// Create the container
var container = new Border
{
  Child = contentVisual,
  Background = Brushes.White,
  BorderBrush = Brushes.Black,
  BorderThickness = new Thickness(1),
};

// Measure and arrange the container
container.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
container.Arrange(new Rect(container.DesiredSize));

// Temporarily add a PresentationSource if none exists
using(var temporaryPresentationSource = new HwndSource(new HwndSourceParameters()) { RootVisual = (VisualTreeHelper.GetParent(container)==null ? container : null) })
{
  // Flush the dispatcher queue
  Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() => { }));

  // Render to bitmap
  var rtb = new RenderTargetBitmap((int)b.ActualWidth, (int)b.ActualHeight, 96, 96, PixelFormats.Pbgra32);
  rtb.Render(container);

  return rtb;
}

FYI, поиск StaticResource никогда не откладывается ни при каких обстоятельствах: это обрабатывается в тот момент, когда XAML загружен и сразу заменяется значением, полученным из полученного ресурса. То Только путь статики возможно Будьте связаны, если он поднял не тот ресурс, потому что два ресурса имели один и тот же ключ. Я просто подумал, что должен это объяснить - это не имеет ничего общего с вашей реальной проблемой.

Другие советы

Ну, чтобы встроить его, вы могли бы просто сделать что-то вроде этого:

<Grid>
    <Grid.Background>
        <VisualBrush>
            <VisualBrush.Visual>
                <!-- blah blah -->
            </VisualBrush.Visual>
        </VisualBrush>
    </Grid.Background>
</Grid>

Если это не сработает, я думаю, что это должно быть что-то конкретное с Visual Экземпляр вы используете (и это потребует дополнительный код для лучшего диагностики).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top