2009-04-27 7 views
12

Wo kann ich genug Informationen darüber finden, wie Brushes arbeitet, um meine eigene System.Windows.Media.Brush zu implementieren? Ich kann mit allem Gepäck fertig werden, aber es ist nicht wirklich offensichtlich, was ich außer Kraft setzen muss, um es zum Laufen zu bringen.Wie implementiere ich einen benutzerdefinierten Pinsel in WPF?


Ja, also wollte ich nicht, dass ich einen vordefinierten Pinsel verwenden möchte. Ich möchte System.Windows.Media.Brush erweitern, was eine abstrakte Klasse ist. Dies alles dient ausschließlich meiner eigenen Erbauung. Ich bin mir nicht einmal sicher, welche Art von Pinsel ich machen könnte. Ich habe nur versucht zu lernen, wie Pinsel funktionieren. Wie in:

public AwesomeBrush : Brush 
{ 

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

    ... // concrete brush stuff 

} 
+0

Es könnte hilfreich sein, ein wenig mehr Informationen darüber zu geben, was Sie zu tun versuchen. Nicht sicher, was ein Pinsel erstellen würde, aber hier ist eine gute Liste der vielen in wpf eingebauten Pinsel: http://msdn.microsoft.com/en-us/library/aa970904.aspx –

Antwort

3

können Sie keine benutzerdefinierte WPF Pinsel machen, indem von der System.Windows.Media.Brush Klasse erben, weil diese Klasse abstrakte Elemente enthält, die intern sind.

Wenn Sie Reflector verwenden den Quellcode System.Windows.Media.Brush Klasse zu betrachten, sehen Sie die folgenden internen abstrakten Methoden siehe:

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); 

Dieser außer Kraft gesetzt werden muß, kann aber nicht sein, weil sie intern sind.

Hinweis: Bearbeitete meine Antwort, weil vorherige Antwort war über System.Drawing.Brush und irrelevant für diese Frage. Besonderer Dank geht an Mikko Rantanen für seinen Kommentar.

+4

Sie können von Brush-Klasse erben - Wie du gesagt hast, es ist abstrakt und abstrakte Klassen müssen vererbt werden. –

+0

Worum geht es Brush, das es vererbt werden kann? Ich weiß, dass alle Implementierungen versiegelt sind, aber wir sollten in der Lage sein, von Brush abzuleiten, richtig? – MojoFilter

+1

Verdammt Sie interne Konstrukteure! Ich wurde schon vorher von dir vereitelt! – MojoFilter

9

Ich hatte einen kurzen Blick auf die vorhandenen Bürsten mit der Reflector. Es scheint, als ob ihre Implementierung ziemlich geschlossen ist und von vielen internal Rohrleitungen abhängt. Während es möglich ist, einen eigenen Pinsel zu implementieren, scheint es, dass es keine unterstützte Option ist. Es könnte sogar sein, dass die WPF-Steuerelemente eng an die vorhandenen Pins gebunden sind und nicht mit einem benutzerdefinierten funktionieren.

Sehr wahrscheinlich ist der beste Weg, etwas wie benutzerdefinierte Pinsel zu erreichen, die Verwendung der DrawingBrush mit einigen komplexen Zeichenlogik. Sie können Zeichenpinsel aus komplexen Formen mit anderen Pinseln erstellen, damit Sie das gewünschte Ziel erreichen können.

Update nach bearbeiten

Da dies für die Bildung ist, könnte man am besten aus dem Reflektor herunterzuladen und zu sehen, dass mit, wie die Bürsten arbeiten. Sie sind nicht dazu gedacht, sich selbst zu implementieren, und da sie sich auf einige internal Klassen stützen, auf die Programmierer normalerweise keinen Zugriff haben, wird es ziemlich schwierig sein, dies zu tun.

Obwohl es interessant ist, dass die Brush documentation eine Bemerkung für Erben hat, um in der richtigen Weise zu erben, von der Bürste zu erben.

Weiteres Updates

Wenn Stochern finde ich eine ganz ordentliche Weise etwas ähnliches auf einem chinese blog zu erreichen. Der Trick besteht darin, eine Markup-Erweiterung zu verwenden, so dass es nur wie ein Pinsel aussieht. In Wirklichkeit erstellt er einen neuen Bildpinsel basierend auf seinen Attributen. Er scheint zu der gleichen Schlussfolgerung gekommen zu sein, dass es einige interne Klassen gibt, die die einfache Implementierung verhindern.

+0

Ich vermute, dass das auch der Fall ist. Ich kann mir nichts vorstellen, was mit den im Framework bereitgestellten Pinsel-Implementierungen nicht möglich wäre. Ich habe mich nur gefragt, ob es vielleicht spaßige Wege gibt, solche Dinge zu komponieren, um es wirklich zur Wiederverwendung zu bringen. – MojoFilter

+0

Ein Update hinzugefügt, das etwas Ähnliches erreicht, ohne Brush zu erweitern. –

+1

Ich frage mich, ob die Notiz in der Bürstendokumentation zu den Erben für Microsoft persönlich war und nicht in das endgültige Dokument aufgenommen werden sollte. Wenn ich mir Reflector anschaue, sieht es so aus, als ob viele der wesentlichen Felder in Brush und auch GradientBrush als intern markiert sind. Also können wir nicht auf sie eingehen. –

3

Ich versuchte jeden möglichen Winkel für eine Lösung zum Erstellen eines benutzerdefinierten Pinsels, von MarkupExtensions zum Herumspielen mit TypeConverter-Attributen, dann dachte ich an mich: Sie erstellen einfach eine Wrapper-Klasse basierend auf DependencyObject, erstellen Sie eine DependencyProperty vom Typ Brush , implementieren Sie Ihre Anpassung und binden Sie dann an die Brush DependencyProperty.

Danach legen Sie die benutzerdefinierten Pinsel in Ressourcen

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

Dann daran binden:

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

Ich denke, das ist besser als die Lösung Markupextension, weil Sie nicht ein in Ressourcen setzen und Daher müssen Sie die benutzerdefinierten Einstellungen bei jeder Verwendung neu definieren.

In jedem Fall scheint dies eine einfache Lösung zu sein, um von irgendeinem Wpf-Objekt zu erben, und mit der Flexibilität von Bindungen können Sie auch an Mitglieder des eingepackten Wpf-Objekts selbst binden.

Hier ist die einfache Klasse:

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   
} 
4

die Frage zu beantworten, warum Sie vielleicht einen benutzerdefinierten Pinsel haben, eine komplexe Geometrie betrachten und Sie wollen es mit einem Gradienten zu füllen, die die Form paßt beim Ändern färbt sich radial vom Mittelpunkt der Form (oder einem beliebigen Startpunkt).

Es gibt keine Möglichkeit, dies mit einer statischen Füllung (die praktisch alle vorhandenen Bürsten beseitigt) zu tun. Anstatt das Objekt immer wieder zu replizieren und zu verschachteln (und die Verschalung so auszuarbeiten, dass alles gut aussieht) und jedes mit einer anderen Farbe zu füllen, ist der einzige praktische Weg, einen Pinsel zu haben, der das zu füllende Objekt betrachten kann .

Dies ist tatsächlich möglich in Forms.

Aber es sieht nicht so aus, als gäbe es eine Möglichkeit, es in WPF zu tun, was bedauerlich ist.

In der Tat sind WPF Bürsten gleichzeitig erstaunlich leistungsstark und überraschend begrenzt. Sie sind eindeutig an ein Konzeptmodell angepasst, aber ich bin mir nicht sicher, ob es neben einigen ziemlich trivialen visuellen Effekten nützlich ist, und wie üblich, wurde es mit seltsamen (schlecht dokumentierten) Parametern komplexer gemacht, was das sehr macht einfach, etwas kompliziert.

Verwandte Themen