私の要件:
UserControl
マップや描画などのカスタム イメージのロジックを処理する永続- ズームまたはパンの移動中に画像にキャッシュを実装するためのコンテナーのセット
VisualBrush
UserControl
エフェクトで使用するコンテナに追加できるのコピー
現在、RenderTargetBitmap を使用してイメージ キャッシングを実装していますが、使用しているVisualBrush
-coveredRectangle
オブジェクトに問題があるようです。
私の質問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 を介してレンダリングされたもの) がまったく表示されないことがわかります。これは、[新規] ボタンをもう一度押して画像をキャッシュにプッシュし、それでもなお新しく作成された画像が表示されません。