.net - ändern - wpf relativesource self




Wie verwende ich WPF-Bindungen mit RelativeSource? (10)

Bechir Bejaoui legt in seinem Artikel hier die Anwendungsfälle der RelativeSources in WPF offen:

Die RelativeSource ist eine Markup-Erweiterung, die in bestimmten Bindungsfällen verwendet wird, wenn wir versuchen, eine Eigenschaft eines bestimmten Objekts an eine andere Eigenschaft des Objekts selbst zu binden, wenn wir versuchen, eine Eigenschaft eines Objekts an einen anderen relativen Elternknoten zu binden. Beim Binden eines Abhängigkeitseigenschaftswerts an einen XAML-Abschnitt im Falle einer benutzerdefinierten Steuerungsentwicklung und schließlich im Fall der Verwendung eines Differenzials einer Reihe gebundener Daten. Alle diese Situationen werden als relative Quellmodi ausgedrückt. Ich werde alle diese Fälle einzeln aufdecken.

  1. Modus Selbst:

Stellen Sie sich diesen Fall vor, ein Rechteck, das wir wollen, dass seine Höhe immer gleich der Breite ist, sagen wir mal ein Quadrat. Dies können wir mithilfe des Elementnamens tun

<Rectangle Fill="Red" Name="rectangle" 
                Height="100" Stroke="Black" 
                Canvas.Top="100" Canvas.Left="100"
                Width="{Binding ElementName=rectangle,
                Path=Height}"/>

In diesem Fall müssen wir jedoch den Namen des Bindungsobjekts angeben, nämlich das Rechteck. Mit der RelativeSource können wir den gleichen Zweck auch anders erreichen

<Rectangle Fill="Red" Height="100" 
               Stroke="Black" 
               Width="{Binding RelativeSource={RelativeSource Self},
               Path=Height}"/>

In diesem Fall müssen wir den Namen des Bindungsobjekts nicht angeben, und die Breite ist immer gleich der Höhe, wenn die Höhe geändert wird.

Wenn Sie die Breite auf die Hälfte der Höhe festlegen möchten, können Sie dies tun, indem Sie der Binding-Markuperweiterung einen Konverter hinzufügen. Stellen wir uns jetzt einen anderen Fall vor:

 <TextBlock Width="{Binding RelativeSource={RelativeSource Self},
               Path=Parent.ActualWidth}"/>

Der obige Fall wird verwendet, um eine gegebene Eigenschaft eines gegebenen Elements mit einer seiner direkt übergeordneten Elemente zu verknüpfen, da dieses Element eine Eigenschaft enthält, die Parent genannt wird. Dies führt uns zu einem anderen relativen Quellmodus, der der FindAncestor-Modus ist.

  1. Modus FindAncestor

In diesem Fall wird eine Eigenschaft eines bestimmten Elements mit einem seiner Eltern, Corse, verbunden sein. Der Hauptunterschied zum obigen Fall besteht darin, dass Sie den Ahnentyp und den Ahnenrang in der Hierarchie bestimmen müssen, um die Eigenschaft zu binden. Versuchen Sie übrigens, mit diesem Stück XAML zu spielen

<Canvas Name="Parent0">
    <Border Name="Parent1"
             Width="{Binding RelativeSource={RelativeSource Self},
             Path=Parent.ActualWidth}"
             Height="{Binding RelativeSource={RelativeSource Self},
             Path=Parent.ActualHeight}">
        <Canvas Name="Parent2">
            <Border Name="Parent3"
            Width="{Binding RelativeSource={RelativeSource Self},
           Path=Parent.ActualWidth}"
           Height="{Binding RelativeSource={RelativeSource Self},
              Path=Parent.ActualHeight}">
               <Canvas Name="Parent4">
               <TextBlock FontSize="16" 
               Margin="5" Text="Display the name of the ancestor"/>
               <TextBlock FontSize="16" 
                 Margin="50" 
            Text="{Binding RelativeSource={RelativeSource  
                       FindAncestor,
                       AncestorType={x:Type Border}, 
                       AncestorLevel=2},Path=Name}" 
                       Width="200"/>
                </Canvas>
            </Border>
        </Canvas>
     </Border>
   </Canvas>

Die obige Situation besteht aus zwei TextBlock-Elementen, die in eine Reihe von Rahmen und Canvas-Elementen eingebettet sind, die ihre hierarchischen Eltern repräsentieren. Der zweite TextBlock zeigt den Namen des angegebenen Elternteils auf der relativen Quellenebene an.

Versuchen Sie also, AncestorLevel = 2 zu AncestorLevel = 1 zu ändern und sehen Sie, was passiert. Versuchen Sie dann, den Typ des Vorfahren von AncestorType = Border zu AncestorType = Canvas zu ändern, und sehen Sie, was passiert.

Der angezeigte Text ändert sich entsprechend dem Ahnen-Typ und Level. Was passiert dann, wenn die Ahnenebene für den Ahnentyp nicht geeignet ist? Das ist eine gute Frage, ich weiß, dass Sie es fragen werden. Die Antwort ist, dass keine Ausnahmen ausgelöst werden und nichts auf der TextBlock-Ebene angezeigt wird.

  1. TemplatedParent

Dieser Modus ermöglicht das Verknüpfen einer bestimmten ControlTemplate-Eigenschaft mit einer Eigenschaft des Steuerelements, auf das die ControlTemplate angewendet wird. Um das Problem hier zu verstehen, ist ein Beispiel unten aufgeführt

<Window.Resources>
<ControlTemplate x:Key="template">
        <Canvas>
            <Canvas.RenderTransform>
                <RotateTransform Angle="20"/>
                </Canvas.RenderTransform>
            <Ellipse Height="100" Width="150" 
                 Fill="{Binding 
            RelativeSource={RelativeSource TemplatedParent},
            Path=Background}">

              </Ellipse>
            <ContentPresenter Margin="35" 
                  Content="{Binding RelativeSource={RelativeSource  
                  TemplatedParent},Path=Content}"/>
        </Canvas>
    </ControlTemplate>
</Window.Resources>
    <Canvas Name="Parent0">
    <Button   Margin="50" 
              Template="{StaticResource template}" Height="0" 
              Canvas.Left="0" Canvas.Top="0" Width="0">
        <TextBlock FontSize="22">Click me</TextBlock>
    </Button>
 </Canvas>

Wenn ich die Eigenschaften eines bestimmten Steuerelements auf seine Steuerelementvorlage anwenden möchte, kann ich den TemplatedParent-Modus verwenden. Es gibt auch eine ähnliche Markup-Erweiterung wie die TemplateBinding, die eine Art kurze Hand des ersten ist, aber die TemplateBinding wird zum Zeitpunkt der Kompilierung am Kontrast des TemplatedParents ausgewertet, der unmittelbar nach der ersten Laufzeit ausgewertet wird. Wie Sie in der folgenden Abbildung sehen können, werden der Hintergrund und der Inhalt von der Schaltfläche aus auf die Steuerelementvorlage angewendet.

Wie verwende ich RelativeSource mit WPF-Bindungen und was sind die verschiedenen Anwendungsfälle?


Da dies die Spitze von Google für dieses Problem ist, dachte ich, ich würde ein paar nützliche Kleinigkeiten:
Hier ist, wie es meist im Code gemacht wird:

Binding b = new Binding();
b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, this.GetType(), 1);
b.Path = new PropertyPath("MyElementThatNeedsBinding");
MyLabel.SetBinding(ContentProperty, b);

Ich kopierte das weitgehend von: http://social.msdn.microsoft.com/Forums/en/wpf/thread/c5a59f07-c932-4715-8774-fa7e8472b75b

Auch die MSDN-Seite ist ziemlich gut, soweit Beispiele gehen: http://msdn.microsoft.com/en-us/library/system.windows.data.relativesource.aspx


Es ist erwähnenswert, dass diejenigen, die über dieses Denken von Silverlight stolpern:

Silverlight bietet nur eine reduzierte Teilmenge dieser Befehle


Hier ist eine visuelle Erklärung im Kontext einer MVVM-Architektur:


Ich habe gerade eine andere Lösung für den Zugriff auf den DataContext eines übergeordneten Elements in Silverlight veröffentlicht, das für mich funktioniert. Es verwendet Binding ElementName .


Ich habe nicht jede Antwort gelesen, aber ich möchte diese Informationen nur im Falle der relativen Quellbefehlsbindung einer Schaltfläche hinzufügen. Wenn Sie relative Quelle mit Mode=FindAncestor , muss die Bindung wie lauten:

Command="{Binding Path=DataContext.CommandProperty, RelativeSource={...}}"

Wenn Sie DataContext nicht in Ihrem Pfad hinzufügen, kann er die Eigenschaft zur Ausführungszeit nicht abrufen.


Stellen Sie sich diesen Fall vor, ein Rechteck, das wir wollen, dass seine Höhe immer gleich der Breite ist, sagen wir mal ein Quadrat. Dies können wir mithilfe des Elementnamens tun

<Rectangle Fill="Red" Name="rectangle" 
                    Height="100" Stroke="Black" 
                    Canvas.Top="100" Canvas.Left="100"
                    Width="{Binding ElementName=rectangle,
                    Path=Height}"/>

In diesem Fall müssen wir jedoch den Namen des Bindungsobjekts angeben, nämlich das Rechteck. Mit der RelativeSource können wir den gleichen Zweck auch anders erreichen

<Rectangle Fill="Red" Height="100" 
                   Stroke="Black" 
                   Width="{Binding RelativeSource={RelativeSource Self},
                   Path=Height}"/>

In diesem Fall müssen wir den Namen des Bindungsobjekts nicht angeben, und die Breite ist immer gleich der Höhe, wenn die Höhe geändert wird.

Wenn Sie die Breite auf die Hälfte der Höhe festlegen möchten, können Sie dies tun, indem Sie der Binding-Markuperweiterung einen Konverter hinzufügen. Stellen wir uns jetzt einen anderen Fall vor:

 <TextBlock Width="{Binding RelativeSource={RelativeSource Self},
                   Path=Parent.ActualWidth}"/>

Der obige Fall wird verwendet, um eine gegebene Eigenschaft eines gegebenen Elements mit einer seiner direkt übergeordneten Elemente zu verknüpfen, da dieses Element eine Eigenschaft enthält, die Parent genannt wird. Dies führt uns zu einem anderen relativen Quellmodus, der der FindAncestor-Modus ist.


Wenn Sie an eine andere Eigenschaft des Objekts binden möchten:

{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}

Wenn Sie eine Eigenschaft für einen Vorfahren erhalten möchten:

{Binding Path=PathToProperty,
    RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}

Wenn Sie eine Eigenschaft auf dem Vorlagen-Elternteil erhalten möchten (so können Sie 2-Wege-Bindungen in einer ControlTemplate erstellen)

{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}

oder, kürzer (das funktioniert nur für OneWay-Bindungen):

{TemplateBinding Path=PathToProperty}

In WPF RelativeSource Bindung werden 3 properties zum Festlegen von:

1. Modus: Dies ist eine enum , die vier Werte haben könnte:

ein. PreviousData ( value=0 ): Er weist dem gebundenen Wert den vorherigen Wert der property zu

b. TemplatedParent ( value=1 ): Dies wird beim Definieren der templates eines beliebigen Steuerelements verwendet und soll an einen Wert / eine Eigenschaft des control gebunden control .

Ex. Definieren Sie ControlTemplate

  <ControlTemplate>
        <CheckBox IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
 </ControlTemplate>

c. Selbst ( value=2 ): Wenn Sie von einem self oder einer property des Selbst binden wollen.

Ex. Senden Sie den CommandParameter checkbox CommandParameter als CommandParameter während Sie den Command auf CheckBox

<CheckBox ...... CommandParameter="{Binding RelativeSource={RelativeSource Self},Path=IsChecked}" />

d. FindAncestor ( value=3 ): Wenn Sie von einem übergeordneten control in Visual Tree binden möchten.

Ex. binden Sie ein checkbox in records ein, wenn ein checkbox für grid , wenn header checkbox ist

<CheckBox IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type iDP:XamDataGrid}},Path=DataContext.IsHeaderChecked,Mode=TwoWay}" />

2. AncestorType: Wenn der Modus FindAncestor dann definiere den Typ des Vorfahren

RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type iDP:XamDataGrid}}

3. AncestorLevel: Wenn der Modus FindAncestor dann welche Ebene eines Sektors (wenn es zwei gleiche Arten von Eltern im visual tree )

RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type iDP:XamDataGrid,AncestorLevel=1}}

Oben sind alle Anwendungsfälle für die RelativeSource binding .

Hier ist ein Ref-Link


Binding RelativeSource={
    RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemType}
}
...

Das Standardattribut von RelativeSource ist die Mode Eigenschaft. Ein vollständiger Satz gültiger Werte wird hier angegeben ( von MSDN ):

  • PreviousData Ermöglicht es Ihnen, das vorherige Datenelement (nicht das Steuerelement, das das Datenelement enthält) in der Liste der angezeigten Datenelemente zu binden.

  • TemplatedParent Verweist auf das Element, auf das die Vorlage (in der das datengebundene Element vorhanden ist) angewendet wird. Dies entspricht dem Festlegen einer TemplateBindingExtension und ist nur anwendbar, wenn sich die Bindung in einer Vorlage befindet.

  • Selbst Bezieht sich auf das Element, für das Sie die Bindung festlegen, und ermöglicht das Binden einer Eigenschaft dieses Elements an eine andere Eigenschaft desselben Elements.

  • FindAncestor Bezieht sich auf den Vorfahren in der übergeordneten Kette des datengebundenen Elements. Sie können dies verwenden, um an einen Vorfahren eines bestimmten Typs oder seiner Unterklassen zu binden. Dies ist der Modus, den Sie verwenden, wenn Sie AncestorType und / oder AncestorLevel angeben möchten.





relativesource