15

独自の System.Windows.Media.Brush を実装するためにブラシがどのように機能するかについての十分な情報はどこで見つけることができますか? 凍結可能な荷物はすべて処理できますが、それを機能させるために何をオーバーライドする必要があるかは明確ではありません。


ええ、定義済みのブラシを使いたいという意味ではありませんでした。抽象クラスである System.Windows.Media.Brush を拡張したいと考えています。これはすべて、純粋に私自身の啓蒙のためです。どんなブラシを作れるかさえわかりません。私はちょうどブラシがどのように機能するかを学ぼうとしていました. 次のように:

public AwesomeBrush : Brush
{

    protected override Freezable CreateInstanceCore()
    {
        return new AwesomeBrush();
    }

    ... // concrete brush stuff

}
4

4 に答える 4

10

Reflectorを使用して、既存のブラシをざっと見てみました。internalそれらの実装はかなりクローズアップされており、多くの配管に依存しているようです。独自のブラシを実装することは可能かもしれませんが、サポートされていないようです。WPF コントロールが既存のブラシに密接に結び付けられており、カスタム ブラシでは機能しない可能性さえあります。

カスタム ブラシに似たものを実現する最善の方法は、複雑な描画ロジックでDrawingBrushを使用することです。他のブラシを使用して複雑な形状から描画ブラシを構成できるため、必要な目標を達成できるはずです。

編集後に更新

これは教育用であるため、Reflector をダウンロードし、それを使用してブラシの動作を確認することをお勧めします。それらは自己実装することを意図しておらず、internalプログラマーが通常アクセスできないいくつかのクラスに依存しているため、そうするのは非常に困難です。

興味深いのは、ブラシのドキュメントに、継承者がブラシから継承する正しい方法をガイドするための注意事項があることです。

その他のアップデート

調べてみると、中国のブログで同様のことを達成するための非常に巧妙な方法を見つけました。トリックは、マークアップ拡張機能を使用して、ブラシのように見せることです。実際には、その属性に基づいて新しいイメージ ブラシを作成します。彼は、簡単な実装を妨げる内部クラスがいくつかあるという同じ結論に達したようです。

于 2009-04-27T18:34:45.613 に答える
5

なぜカスタム ブラシが必要なのかという質問に答えるには、複雑なジオメトリを考えてみましょう。形状の中心 (または任意の開始点) から放射状に色を変えながら、形状に一致するグラデーションで塗りつぶしたいとします。

これを静的な塗りつぶしで行う方法はありません (これにより、既存のブラシがほとんどすべて削除されます)。オブジェクトを何度も複製してネストし (そして、すべてが正しく見えるように外皮を処理する)、それぞれを異なる色で塗りつぶす以外に、唯一の実用的な方法は、塗りつぶされているオブジェクトを見ることができるブラシを用意することです。 .

これは実際に Forms で実行できます。

しかし残念なことに、WPF でそれを行う方法はないようです。

実際、WPF のブラシは驚くほど強力であると同時に、驚くほど制限されています。それらは明らかにいくつかのコンセプトモデルに合わせて設計されていますが、それがかなり些細な視覚効果を超えて役立つものであるかどうかはまったくわかりません。シンプルでやや複雑。

于 2012-02-15T17:34:52.943 に答える
4

MarkupExtensions を使用することから TypeConverter 属性をいじることまで、カスタム ブラシを作成するための解決策として考えられるすべての角度を試してみたところ、気が遠くなりました。単に DependencyObject に基づいてラッパー クラスを作成し、Brush タイプの DependencyProperty を作成し、カスタマイズを実装するだけです。次に、Brush DependencyProperty にバインドします。

その後、リソースにカスタム ブラシを配置します。

  <l:CustomBrush x:Key="CustomBrush" Brush="Magenta" />

次にそれにバインドします。

  <Line X1="0" Y1="-5" X2="200" Y2="-5" 
        Stroke="{Binding Source={StaticResource CustomBrush}, Path=Brush}" 
        StrokeThickness="12"/>

これは MarkupExtension ソリューションよりも優れていると思います。これは、リソースに配置できないため、使用するたびにカスタム設定を再定義する必要があるためです。

いずれにせよ、これは任意の Wpf オブジェクトから継承するための簡単な解決策のように思われます。Bindings の柔軟性により、ラップされた Wpf オブジェクト自体のメンバーにバインドすることもできます。

簡単なクラスは次のとおりです。

public class CustomBrush : DependencyObject
{
   public CustomBrush()
   {
      this.Brush = Brushes.Azure;      
   }

   #region Brush DependencyProperty

   [BindableAttribute(true)]
   public Brush Brush
   {
     get { return (Brush)GetValue(BrushProperty); }
     set { SetValue(BrushProperty, value); }
   }
   public static readonly DependencyProperty BrushProperty =
      DependencyProperty.Register(
         "Brush",
         typeof(Brush),
         typeof(CustomBrush),
         new UIPropertyMetadata(null));

   #endregion         
}
于 2010-03-18T21:18:54.477 に答える
3

クラスから継承してカスタム WPF ブラシを作成することはできませんSystem.Windows.Media.Brush。そのクラスには内部の抽象メンバーが含まれているためです。

Reflector を使用してSystem.Windows.Media.Brushクラスのソース コードを表示すると、次の内部抽象メソッドが表示されます。

internal abstract DUCE.ResourceHandle AddRefOnChannelCore(DUCE.Channel channel);
internal abstract DUCE.Channel GetChannelCore(int index);
internal abstract int GetChannelCountCore();
internal abstract DUCE.ResourceHandle GetHandleCore(DUCE.Channel channel);
internal abstract void ReleaseOnChannelCore(DUCE.Channel channel);

これらはオーバーライドする必要がありますが、内部的なものであるためオーバーライドできません。

注:以前の回答はSystem.Drawing.Brushこの質問に関するものであり、無関係であるため、私の回答を編集しました。Mikko Rantanen 氏のコメントに感謝します。

于 2009-04-27T18:15:59.623 に答える