9 Stimmen

Datenbindung außerhalb des visuellen Baums. Daten Kontext Überbrückung

Ich versuche, ein dynamisches Verhalten an ein visuelles Element außerhalb der logischen und visuellen WPF-Bäume zu binden.

Mein Problem ist, dass die RadChart-Plot-Farbe in (quasi Pfad) gegeben ist: RadChart.SeriesMapping.LineSeriesDefinition.Appearance.Stroke

Ursprünglich wollte ich das an eine Eigenschaft des Diagramms datacontext in XAML binden. Naiverweise schrieb ich einfach eine reguläre {Binding PlotBrush}

Der Compiler gab den Fehler "Cannot Find Governing FrameWorkelement" zurück. Nach der Lektüre, ich vermute, dass dies bedeutet, dass die Auflösung der datacontext nach oben die Hierarchie nicht funktioniert. Denn seine Vorfahren (in XAML) haben andere Typen als FrameWorkElement und andere Beziehungen als den Inhalt eines Inhaltssteuerelements. Zumindest ist das mein derzeitiges Verständnis davon. Bitte korrigieren Sie mich.

Ich habe also die "DataContext Bridge" gefunden. http://www.codeproject.com/KB/WPF/AttachingVirtualBranches.aspx

Einfach ausgedrückt heißt es, dass Sie binden die Datacontext-Eigenschaft des Framework-Elements, dem der Datacontext zur Laufzeit zugewiesen wird (nicht eines der Elemente, die ihn erben) zu den Datentext einer FrameWorkElement-Instanz innerhalb der Ressourcen . Dann wird dieselbe Instanz des Ressourcenobjekts verwendet, um an die Datacontext-Eigenschaft eines "Zweigs" zu binden, den Sie an die DataContext-Vererbungsdynamik "anhängen" möchten. Der Autor des Artikels hatte jedoch den Luxus, die Validierungsregel für die beobachtete Eigenschaft implementieren zu können. SolidColorBrush ist versiegelt und ich kann mir vorstellen, dass es ziemlich viel Arbeit wäre, einen kompletten Brush zu implementieren, selbst mit einem Dekorator.

In meinem Fall hilft mir das nicht, zu tun, was ich will, aber ich bin "so nah". Ich frage mich also, ob es irgendeinen Aspekt der XAML-Tricks gibt, der mir helfen könnte.

<Window.Resources>
    <local:FrameWorkElement x:Key="DataContextBridge"/>
</Window.Resources>

Es ist jedoch unklar, wie ich dies nutzen kann. Es gibt kein Objekt, dessen Datacontext gesetzt werden soll. AppearanceSettings ist kein FrameWorkElement.

<telerik:SeriesAppearanceSettings>
   <telerik:SeriesAppearanceSettings.Stroke>
       Ok, how do I use the fact that I can access the datacontext here?                                         
   </telerik:SeriesAppearanceSettings.Stroke>
</telerik:SeriesAppearanceSettings>

Der nächste Schritt war also, ob ich das Pinselobjekt irgendwie direkt bekommen könnte. Ich experimentierte mit dieser Art von Sache, nur herumspielen:

.cs :

public class ObservableBrush : FrameworkElement
{
    public Brush Brush
    {
        get { return (Brush) GetValue(BrushProperty); }
        set { SetValue(BrushProperty, value); }
    }

    public static readonly DependencyProperty BrushProperty =
        DependencyProperty.Register("Brush", typeof (Brush), typeof (ObservableBrush), new UIPropertyMetadata(new SolidColorBrush(Colors.Black)));
}

Anfang von XAML:

<Window.Resources>
    <local:ObservableBrush x:Key="StrokeBrush"/>
</Window.Resources>

Inline-XAML:

<telerik:SeriesAppearanceSettings.Stroke>
     <Binding Path="Brush">
     <Binding.Source>
          <Binding Source="{StaticResource ResourceKey=StrokeBrush}" Path="DataContext"/>
     </Binding.Source>                                            
     </Binding>                                     
</telerik:SeriesAppearanceSettings.Stroke>

"Binding" ist kein Framework-Element, und "Source" ist auch keine Abhängigkeitseigenschaft, so dass sich die Laufzeit natürlich beschwert. Ich bin mir bewusst, dass die Brush-Eigenschaft nie etwas anderes als den in der Registrierung der Abhängigkeitseigenschaft angegebenen Standardwert zurückgeben wird.

Ich befasse mich nun schon den zweiten Tag mit diesem Problem. Ich denke, dass meine nächsten beiden Versuche sein werden: * ObservableBrush zu einem tatsächlichen Pinsel machen. Dann programmatisch festgelegt (effektiv mit Standard dynamische Ressourcenbindung statt). Ich mag das nicht. Ich wollte Databinding Arbeit zu machen. * Einen BRUSH anstelle von DATACONTEXT überbrücken.

Der XAML-Teil davon funktioniert einwandfrei:

<telerik:SeriesAppearanceSettings.Stroke>
     <Binding Source="{StaticResource ResourceKey=StrokeBrush}" Path="Brush"/>
</telerik:SeriesAppearanceSettings.Stroke>

Aber wieder, wie binde ich den Pinsel an die DataContext-Eigenschaft? Gibt es einige überschreiben, die ich innerhalb ObservableBrush verwenden können, um Brush dynamisch die in den Datacontext folgen?

Wie wäre es, ein falsches visuelles Element innerhalb des Baums zu erstellen und ihm dann ZWEI Bindungen zuzuordnen?

<!-- Within the visual tree scope -->
<SomeFrameWorkElementType>
     <SomeFrameWorkElemetType.SomeBrushProp>
         <Binding Source="{StaticResource ResourceKey=StrokeBrush}" Path="Brush" Mode="OneWayToSource"/>
         <Binding Stroke/>
     </SomeFrameWorkElemetType.SomeBrushProp>
<SomeFrameWorkElementType>

Und das wird die beiden Bindungen irgendwie "verbinden"?

Oder gibt es eine (un)offizielle "Hilfsklasse" für diese Art von Funktionalität?

Oder bin ich barking up the wrong tree, und (viel) besser weg lösen dies in der Code-Behind durch dynamische Ressource Bindung?

Haben Sie eine Idee oder eine Beobachtung, wie es weitergehen soll? Andere als auf meine offensichtliche Selbstzerstörung für das Beharren auf Datenbindung, wenn dynamische Ressourcen sollten dieses Problem zu lösen.

13voto

Markus Hütter Punkte 7647

Sie haben dort einen guten Artikel von Josh Smith gefunden, der allerdings etwas veraltet ist. Derselbe Autor hat etwa ein Jahr später einen noch besseren Artikel geschrieben, der so ziemlich die gleiche Frage behandelt, aber bessere Antworten enthält: Künstliche Vererbung Kontext

Dort verwendet er die Klasse DataContextSpy und obwohl ich immer noch nicht ganz verstehe, was Sie zu erreichen versuchen, werde ich versuchen, Ihnen zu zeigen, wie Sie es verwenden:

<Grid><!-- this is some container where its DataContext has the PlotBrush Property-->
    <Grid.Resources>
        <spy:DataContextSpy x:Key="Spy"/>
    </Grid.Resources>
    <telerik:thisIsYourControl>
        <telerik:SeriesAppearanceSettings.Stroke>
             <Binding Source="{StaticResource Spy}" Path="DataContext.PlotBrush"/>
        </telerik:SeriesAppearanceSettings.Stroke>
    </telerik:thisIsYourControl>
<Grid>

Ich hoffe, dass dies für Sie hilfreich ist und funktioniert. Ich habe nicht telerik Steuerelemente vor verwendet, das ist, warum ich nicht ein komplettes Beispiel zu codieren, noch hoffen, dass dies deckt es.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X