0

ControlTemplate を writeableBitmap にレンダリングすることを目的としたコードがいくつかあります。WBMP を作成するコードは次のとおりです。

    private static void OnMarkerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var template = e.NewValue as ControlTemplate;
        if (template != null)
        {
            var c = new Marker();
            c.Template = template;
            c.ApplyTemplate();
            c.MeasureArrange();
            c.Width = c.DesiredSize.Width;
            c.Height = c.DesiredSize.Height;

            // _cachedBitmap is of type WriteableBitmap
            _cachedBitmap = c.RenderToBitmap();
        }
    }   

次の拡張メソッドが定義されている場所:

    internal static void MeasureArrange(this UIElement element)
    {
        element.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
        element.Arrange(new Rect(new Point(0, 0), element.DesiredSize));
    }

    public static WriteableBitmap RenderToBitmap(this FrameworkElement element)
    {
        int width = (int)element.DesiredSize.Width;
        int height = (int)element.DesiredSize.Height;

#if SILVERLIGHT
        var result = new WriteableBitmap(width, height);
        result.Render(element, new TranslateTransform());
        result.Invalidate();
        return result;
#else
        // WPF Impl works just fine
        var bmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);

        bmp.Render(element);
        return new WriteableBitmap(bmp);
#endif         
    }

マーカーは空のコントロールとして定義されています

public class Marker : Control
{         
}

問題はこれです。WPF では、ビットマップの作成を最初に試みた後、Silverlight と同様に、これはすべて正常に機能します。ただし、最初の試行は失敗し、正しいサイズ (7*7、つまり 49 ピクセル) の WriteableBitmap が返されますが、int[] Pixels配列はすべてゼロです。

役立つかもしれないいくつかのこと。で WriteableBitmap を作成する直前RenderToBitmap、要素の幅/高さは 7,7、望ましいサイズは (7,7) ですが、ActualWidth/ActualHeight は (0,0) です。WPF では、すべて (7,7) であると考えています。したがって、これはレイアウトの問題ではなく、レイアウトの問題である可能性があります

参考までに、Marker と ControlTemplate がビジュアル ツリーに到達することはありません。これは純粋にキャッシュされたビットマップの実装です。

何か案は?

4

1 に答える 1

0

あはは!答えが見つかりました。理由はわかりませんが。「答え」のダニは、それを説明できる人なら誰にでも行きます。

ActualWidth / ActualHeight が非同期的に評価されることを示唆するこのリンクを見つけたので、適切な場所の BeginInvoke で問題を解決できます。なぜこれは WPF では機能するのに Silverlight では機能しないのですか?

        var c = new PointMarker();
        c.Template = pointMarkerTemplate;
        c.ApplyTemplate();

        // DispatcherUtil is just a proxy around Dispatcher.BeginInvoke
        DispatcherUtil.Instance.BeginInvoke(() =>
        {
            c.MeasureArrange();
            c.Width = c.DesiredSize.Width;
            c.Height = c.DesiredSize.Height;
            series._pointMarkerCache = c.RenderToBitmap();
            series.OnInvalidateParentSurface();
        });
于 2012-02-29T21:21:59.590 に答える