17

通常の WPF レンダリングをハイジャックして、コントロールをプリミティブに分割し、レイアウト管理を行い、バインディングなどを適用したいと思います。

私が理解している限り、WPF でのレンダリング全体は、依存関係プロパティ システムによって定義された値を使用して、レイアウト マネージャーによって計算された位置でのプリミティブ (テキスト、画像、線、曲線) のレンダリングに要約されます。独自のプリミティブ レンダリング ロジックを提供できれば、たとえばカスタム ドキュメント タイプにレンダリングしたり、ネットワーク経由で実際のレンダリング用にプリミティブを転送したりできます。

私の計画は次のとおりです。

  1. カスタムを実装しますDrawingContext。は、、などDrawingContextの一連のメソッドを定義する抽象クラスです。この機能には、独自の実装を提供する必要があります。DrawEllipseDrawTextDrawImage
  2. WPFUserControlを作成し、指定された .xml に強制的にレンダリングしますDrawingContext

ただし、次の問題が発生しました。

  1. DrawingContext簡単にオーバーライドできない抽象内部メソッドvoid PushGuidelineY1(double coordinate)とが含まれています。void PushGuidelineY2(double leadingCoordinate, double offsetToDrivenCoordinate)(もしかしたら、これを克服するためのトリックがあるのでしょうか?)
  2. ビジュアル全体DrawingContextを?にレンダリングする方法はないようです。なんで?

私は次のようなことができます

void RenderRecursively(UIElement e, DrawingContext ctx)
{
    e.OnRender(ctx);
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(e); i++)
        RenderRecursively((UIElement)VisualTreeHelper.GetChild(e, i), ctx);
}

—しかし、をレンダリングする直接的な方法があるのだろうかUIElement. (もちろん、この問題は小さな問題ですが、インフラストラクチャがないことを考えると、これが適切な方法であるかどうか疑問に思います。)

DrawingContextでは、から継承するためのものではありませんか? カスタムを提供するという全体的なアイデアはDrawingContext正しい方向への一歩ですか、それとも戦略を再考する必要がありますか? カスタム コンテキストへの描画は WPF でサポートされていますか、それとも別のインターセプト ポイントを探す必要がありますか?

4

4 に答える 4

4

DrawingContext(他の人が述べたように)独自の実装を提供できないため、あなたのアプローチは機能しないと思います。

代わりに次のことをお勧めします。WPF レンダリングを「平坦化」するには、WPF でビジュアルを XPS ドキュメントにエクスポートします。そのプロセス中、すべてのレンダリングは基本的に単純なレンダリング プリミティブとして列挙され、残るCanvasのは 、基本的な形状、グリフ、およびその他の描画プリミティブだけです。

次に、ドキュメントのページ内のビジュアルを反復処理します。私の知る限り、結果のビジュアルはプリミティブのみで構成されるため、 を呼び出す必要はありませんOnRender。代わりに、これにより、ビジュアル インスタンスを外部からイントロスペクトできます ( instanceof-cascades を使用し、プロパティを読み取り/解釈します)。WPF と同じようにプロパティを解釈する必要があるため、それでもかなりの作業が必要ですが、私が見る限り、これは少なくとも多くの主要なユース ケースで機能するはずです。

于 2013-08-21T13:43:22.123 に答える
4

反対方向からこの問題に取り組む必要があるかもしれません。独自の を提供することを目指す代わりにDrawingContext、WPF にDrawing. したがって、それはあなたが目指している「プッシュ」アプローチよりも「プル」アプローチですが、同じ場所に到達できるようにする必要がありますDrawing。ビジュアル ツリー。これは、カスタム への呼び出しから発見したであろうすべてのものを歩いて発見できるデータ構造ですDrawingContext

これは、Sebastian が言及している XPS ドキュメント エクスポートが社内で使用しているのと同じ基本的なアプローチだと思います。ただし、XPS API を介して使用するよりも、自分で直接使用する方が直接的な方法です。

中心にあるのはかなり単純なものです: VisualTreeHelper.GetDrawing. これは を返しますDrawingGroup。(Drawingは抽象基本クラスです。) そのドキュメント ページには、取得したツリーをたどる方法が示されています。残念ながら、これはすべての仕事を行うわけではありません。それを呼び出したノードのビジュアルを提供するだけで、そのノードに子がある場合、それらは含まれません。

そのため、残念ながら、すでに計画していたように、ビジュアル ツリーを再帰するものを作成する必要があります。また、正しい結果を得るには、ビジュアルに関連付けられている不透明マスク、非マスクベースの不透明度、クリップ領域、効果、および変換を処理する必要もあります。提案されたアプローチを正しく機能させるには、それもすべて行う必要があったため、ここでは何も変わりません。(Sebastian が示唆するように、XPS API を使用する潜在的な利点の 1 つは、このすべてが自動的に行われることです。ただし、XPS ドキュメントから必要な形式で情報を抽出するのはユーザーの問題であり、それによって、必要な情報が失われる可能性があります。保存したい場合があります。)

于 2013-08-21T14:18:20.333 に答える
1

独自に記述しようとする代わりに、メソッドDrawingContextから派生するクラス、FrameworkElementまたはそのメソッドでアクティビティを実行するクラスを作成することUIElementもできます。の指定された実装を引き続き使用する必要がありますが、引数と操作の順序を制御できます。セカンダリ ソースからのプリミティブと命令を引き続き解析でき、1 つの UIElement/FrameworkElement が実行時に命令を作成できます。VisualOnRenderDraw[Something]

于 2013-08-22T16:33:43.817 に答える