RENDERTARGETBITMAP + RESOMENT A VisualBrush = неполное изображение
-
27-09-2019 - |
Вопрос
Я нашел новый поворот на вопрос «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.
У меня есть подлый подозритель, это может быть вызвано тем, что его ресурс, и этот ленивый ресурс не включен. Так что возможное исправление было бы как-то (???), принудительно разрешение всех статических ссылок на ресурсы перед рендерингом. Но я не имею абсолютно понятия, как это сделать.
Кто-нибудь есть исправить для этого?
Решение
У вас есть две проблемы:
- Вы не установили презентации на ваши визуальные настолько загруженные события, не будут стрелять.
- Вы не промыли очередь диспетчера. Без промывки очереди диспетчера любые функции, которые используют обратные вызовы диспетчера, не будут работать.
Непосредственная причина вашей проблемы - неспособность заподернуть очередь диспетчера, поскольку 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
Экземпляр вы используете (и это потребует дополнительный код для лучшего диагностики).