web-dev-qa-db-ja.com

WPFでウィンドウに描画する方法(ベストプラクティス)?

画面に描画するDrawメソッドが必要な、ゲームのような小さなインタラクティブなアプリケーションを作成しようとしていますが、WPFのメソッドを構造化する方法がわかりません。

これがWinformsの場合、次のように使用できます。

public void Draw (Graphics g)
{

}

しかし、WPF Window、xamlで何を保持する必要がありますか(現在はGridのみです)、このDrawメソッドは引数として何を受け取る必要がありますか?

最初にこれを機能させるためにこのようにしたいので、それをさらにWPFにする方法などを考えることができます。しかし、今はこれを機能させることにもっと興味があります。

25
Joan Venge

通常、WPFで完全に異なる方法で「描画」します。

Windowsフォーム/ GDIでは、グラフィックAPIは即時モードのグラフィックAPIです。ウィンドウが更新または無効化されるたびに、グラフィックを使用してコンテンツを明示的に描画します。

ただし、WPFでは、動作が異なります。直接描画することはほとんどありません。代わりに、保持モードのグラフィックAPIです。オブジェクトを配置する場所をWPFに指示すると、描画が自動的に行われます。

それを考える最良の方法は、Windowsフォームで「X1からY1に線を引く。次にX2からY2に線を引く。その後...」と言うことです。また、画面が無効になるため、「再描画」する必要があるたびにこれを繰り返します。

WPFでは、代わりに「X1からY1へのラインが必要です。X2からY2へのラインが必要です。」と言います。 WPFは、いつ、どのように描画するかを決定します。

これは、シェイプをCanvasに配置し、WPFにすべてのハードワークを実行させることによって行われます。

20
Reed Copsey

オブジェクトが多すぎてすぐに描画できない場合(巨大なビジュアルツリー)、別のオプションとして、WriteableBitmapを使用する方法があります。 Pixelsプロパティを使用してピクセルを設定するか、Renderメソッドを使用してUIElementsを描画します。

9
Erno

私はこの例のようにOnRenderメソッドを使用することを好みます:

protected override void OnRender(DrawingContext drawingContext)
{
    base.OnRender(drawingContext);
     drawingContext.DrawRectangle(null, new Pen(Brushes.Black, 2), new Rect(0, 0, ActualWidth, Height));
}
6
Marek Kwiendacz

WPFでDrawループタイプの動作を実装するには、CompositionTarget.Renderingイベントを使用できます。これは、WPF描画システムがフレームをペイントしているときに、フレームごとに1回発生します。

他の人が指摘したように、これはWPFにあまり対応していませんが、動作し、WPFアプリからより即座に描画動作を取得するために使用できます。

ほとんどの場合、単一のルートキャンバスを使用して、CompositionTarget.Renderingイベントの要素のCanvas位置を更新します。

たとえば、楕円を画面全体に飛ばすには、次のようにします。

XAMLで(サイズが640 x 480のウィンドウの場合):

<Canvas x:Name="theCanvas">
    <Ellipse x:Name="theEllipse" Height="10" Width="10" Fill="Black" />     
</Canvas>

上記のXAMLが含まれているウィンドウのコードビハインドで(CompsitionTargetオブジェクトを表示するには、System.Windows.Mediaへの参照を追加してください。

    public static Random Rand = new Random();
    public View()
    {
        InitializeComponent();
        CompositionTarget.Rendering += CompositionTarget_Rendering;
    }

    void CompositionTarget_Rendering(object sender, System.EventArgs e)
    {
        double newLeft = Rand.Next(0, 640);
        double newTop = Rand.Next(0, 480);

        theEllipse.SetValue(Canvas.LeftProperty,newLeft);
        theEllipse.SetValue(Canvas.TopProperty, newTop);
    }
4
Brad Cunningham

YowはCanvasを追加(またはCanvasのグリッドを変更)してから、その上に描画します。 これはMicrosoftがキャンバス上に描画することを意味します

また、私は この他の質問 があなたの質問にどのように関連しているかはわかりませんが、チェックしてみてください。

2
Felix Martinez