Мои требования:Как заставить RenderTargetBitmap и VisualBrush играть вместе?
- упорной
UserControl
, который обрабатывает логику для пользовательского изображения, такие как карта или рисунок - набор контейнеров для реализации кэширования на изображение во время масштабирования или панорамирования движений
VisualBrush
копииUserControl
, что я могу добавить к контейнерам для использования с эффектами
я в настоящее время реализовать кэширование изображений с RenderTargetBitmap, но это, кажется, проблема с VisualBrush
-накрытых Rectangle
объектов, которые я использую.
Мой вопрос: Что я могу добавить/изменить в этом коде, чтобы получить эти VisualBrush
объекты для визуализации правильно после RenderTargetBitmap
их использует? Какая странная вещь RenderTargetBitmap
делает то, что делает VisualBrush
невидимым?
Это проблема, которую я не смог воспроизвести без приличного количества кода.
В моем файле XAML у меня есть:
<Window x:Class="ElementRender.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="350" Width="525">
<Grid>
<Grid Name="_contentContainer">
<Rectangle Fill="White"/>
<Grid Name="_content">
<Grid Name="_back"/>
<Grid Name="_body"/>
</Grid>
</Grid>
<StackPanel VerticalAlignment="Bottom" Orientation="Horizontal">
<Button Content="New" Name="New"/>
<Button Content="Move" Name="Move"/>
<Button Content="Update" Name="Update"/>
</StackPanel>
</Grid>
</Window>
и .xaml.cs:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
public partial class MainWindow : Window
{
private const int imageWidth = 150;
private const int imageHeight = 150;
private readonly UserControl Control;
public MainWindow()
{
InitializeComponent();
// User Control setup
Control = new UserControl() {
Width = imageWidth, Height = imageHeight,
Content = BuildImage()
};
_body.Children.Add(SoftCopy(Control));
// event setup
Move.Click += (sender, e) => _content.RenderTransform = new TranslateTransform(50, 50);
New.Click += (sender, e) => {
HardCopy();
_content.RenderTransform = null;
Control.Content = BuildImage();
};
}
private FrameworkElement BuildImage()
{
return new Rectangle{Fill=Brushes.Blue};
}
private void HardCopy()
{
int width = (int) _contentContainer.ActualWidth;
int height = (int) _contentContainer.ActualHeight;
// render the current image
var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (var context = dv.RenderOpen())
{
var brush = new VisualBrush(_contentContainer) { Opacity = .5 };
context.DrawRectangle(brush, null, new Rect(0, 0, width, height));
}
rtb.Render(dv);
var lastRender = new Image
{
Source = rtb,
Stretch = Stretch.None,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Width = width,
Height = height
};
_back.Children.Clear();
_back.Children.Add(lastRender);
}
private FrameworkElement SoftCopy(FrameworkElement element)
{
return new Rectangle{Fill= new VisualBrush(element), Width=element.Width, Height=element.Height};
}
}
Несколько помогают заметки о коде:
- в XAML в
_contentContainer
работы сHardCopy()
, чтобы скопировать текущие изображения в кэш изображения,_back
. SoftCopy
возвращает элемент FrameworkElement, который выглядит точно так же, как в прошлом, но без каких-либо преобразований, эффектов или визуальных родителей. Это очень важно.BuildImage
имитирует создание нового изображения, которое будет вставлено в кеш после того, как исходное изображение каким-то образом было преобразовано.
Если построить и запустить приложение с удалением SoftCopy()
из _body.Children.Add(SoftCopy(Control));
, вы видите эффект, который я хочу получить: новый элемент приклеивается над старым элементом, а старый элемент, кажется, сохранить его преобразование.
В качестве альтернативы, если вы вырезали линию var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
от HardCopy
, функция кеширования нарушена, но SoftCopy отображается правильно.
Однако, если вы запустите приложение как есть, вы заметите, что новый BlueRectangle (как визуализируется с помощью VisualBrush) вообще не отображается, пока вы снова не нажмете кнопку «Создать», нажав изображение на кеш и не показывая вам новое созданное изображение.
Вопрос был полностью рассмотрен здесь: http://stackoverflow.com/questions/2851236/rendertargetbitmap-resourced-visualbrush-incomplete-image –