【发布时间】:2012-11-02 01:16:22
【问题描述】:
我的要求:
- 一个持久的
UserControl处理自定义图像的逻辑,例如地图或绘图 - 一组容器,用于在缩放或平移移动期间对图像进行缓存
-
VisualBrushUserControl的副本,我可以将其添加到容器中以与效果一起使用
我目前使用 RenderTargetBitmap 实现图像缓存,但这似乎与我正在使用的 VisualBrush-covered Rectangle 对象有问题。
我的问题:在RenderTargetBitmap 使用VisualBrush 对象后,我可以在此代码中添加/更改什么以正确呈现它们? 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模拟在初始图像以某种方式转换后构建要粘贴到缓存上的新图像。
如果您构建并运行从_body.Children.Add(SoftCopy(Control)); 中删除SoftCopy() 的应用程序,您会看到我想要得到的效果:新元素粘贴在旧元素之上,而旧元素似乎保留了它的变换.
或者,如果您从HardCopy 中删除var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); 行,缓存功能将被破坏,但SoftCopy 会正确显示。
但是,如果您按原样运行应用程序,您会注意到新的 BlueRectangle(通过 VisualBrush 呈现)根本不会显示,直到您再次点击“新建”按钮,将图像推送到缓存,但仍然没有向您显示新创建的图像。
【问题讨论】:
-
这个问题在这里得到了充分的解决:stackoverflow.com/questions/2851236/…
标签: c# .net wpf visualbrush rendertargetbitmap