2010-09-08 7 views
25

Was mache ich hier falsch ?:Relative von einem ToolTip oder ContextMenu Bindung

<GridViewColumn> 
    <GridViewColumn.CellTemplate> 
     <DataTemplate> 
      <Button> 
      <Button.ToolTip> 
       <TextBlock Text="{Binding Path=Title, RelativeSource={RelativeSource AncestorType=Window}}" /> 

Das ist nur ein vereinfachtes Beispiel ist, das ohnehin nicht funktioniert :) Eigentlich brauche ich einen Wert von einer anderen Eigenschaft zu erhalten das ist im Bereich des DataContext des Fensters.

Hilf mir bitte.

Antwort

63

Dies ist schwierig, da ToolTip nicht Teil des VisualTree ist. Here Sie sehen eine coole Lösung für das gleiche Problem mit ContextMenus. Genauso können Sie den ToolTip verwenden.

UPDATE
Leider ist die Verbindung weg und ich habe nicht den angegebenen Artikel mehr gefunden.
Soweit ich mich erinnere, hat der referenzierte Blog gezeigt, wie man an einen DataContext eines anderen VisualTree bindet, was oft beim Binden von einer QuickInfo, einem ContextMenu oder einem Popup notwendig ist.

Eine gute Möglichkeit, dies zu tun, ist die gewünschte Instanz (z. B. ViewModel) innerhalb der Tag-Eigenschaft des PlacementTarget bereitzustellen. Das folgende Beispiel macht dies eine Befehls Instanz eines Ansichtsmodell für den Zugriff auf:

<Button Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=Self}}"> 
    <Button.ContextMenu> 
    <ContextMenu> 
     <MenuItem Command="{Binding PlacementTarget.Tag.DesiredCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" .../> 
    <ContextMenu> 
    </Button.ContextMenu> 
</Button> 

ich es nicht getestet und seine lange ich das tat das letzte Mal. Bitte machen Sie einen Kommentar, wenn es nicht für Sie funktioniert.

UPDATE 2

Als Original-Link, dass diese Antwort über gegangen geschrieben wurde, schlug ich archive.org und found the original blog entry. Hier ist sie, wörtlich aus dem Blog:

Da ein ContextMenu in WPF nicht innerhalb der visuellen Struktur existiert von Ihrer Seite/Fenster/Steuerung per se, Bindungsdaten ein wenig schwierig sein kann. Ich habe High und Low über das Internet dafür gesucht, und die meisten gemeinsame Antwort scheint zu sein "tun Sie es einfach in den Code hinter". FALSCH! Ich kam nicht in die wunderbare Welt von XAML zurück zu Dinge im Code hinter zu gehen.

Hier ist mein Beispiel, mit dem Sie an eine Zeichenfolge binden können, die als eine Eigenschaft Ihres Fensters existiert.

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     MyString = "Here is my string"; 
    } 

    public string MyString 
    { 
     get; 
     set; 

    } 
} 


<Button Content="Test Button" 
    Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"> 
    <Button.ContextMenu> 
    <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, 
      RelativeSource={RelativeSource Self}}" > 
     <MenuItem Header="{Binding MyString}"/> 
    </ContextMenu> 
    </Button.ContextMenu> 
</Button> 

Der wichtige Teil ist der Tag auf der Schaltfläche (obwohl Sie genauso leicht die Datacontext der Taste einstellen könnten). Dies speichert einen Verweis auf das übergeordnete Fenster. Das ContextMenu kann über die Eigenschaft PlacementTarget dieses Objekts auf zugreifen. Sie können dann diesen Kontext nach unten durch Ihre Menüpunkte übergeben.

Ich gebe zu, das ist nicht die eleganteste Lösung der Welt. Allerdings ist es besser, Dinge im Code dahinter zu setzen. Wenn jemand eine noch bessere Möglichkeit hat, dies zu tun, würde ich es gerne hören.

+0

Das ist es! Vielen Dank! – Agzam

+0

Diese Verbindung ist tot. Können Sie die fehlenden Informationen ausfüllen? –

+1

@ Bill Ich habe nicht den Link mehr gefunden, aber ich habe versucht, die Art und Weise zu erklären, wie das Problem gelöst werden kann. – HCL

-2

Ich denke, es sollte wie folgt geschehen:

{Binding Path=Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" 
+0

Nein ... funktioniert nicht. Ich habe das bereits ausprobiert ... – Agzam

+0

Dies funktioniert nicht, weil der Haupt-VisualTree nicht über den ToolTip verfügbar ist. Siehe meine Antwort. – HCL

+0

yah Entschuldigung, habe nicht wirklich bemerkt, dass es in einem Tooltip war. – mdm20

0

Da ContextMenu ist nicht in visuellen Struktur, Bindung wird nicht funktionieren. eine einfache Lösung verwendet Proxy-Muster, können Sie eine Wrapper-Klasse erstellen, die von DependencyObject erbt und hat eine DependencyProperty, die eine DataContext Ihrer Window halten, dann können Sie eine Ressource des Proxy in XAML und schließlich binden Sie Ihre MenuItem Befehl an Ihr gewünschter Befehl über das Proxy-Objekt.
Beispiel Proxy:

Public class ProxyClass : DependencyObject 
{ 
    Public object Data {get; set;} 
    public static readonly DependencyProperty DataProperty = DependencyProperty.Register("DataProperty", typeof(object), typeof(ProxyClass), new FrameworkPropertyMetadata(null)); 

} 

Wie in XAML verwenden:

<Window DataContext="{Binding MyViewModel}"> 
... 
<Window.Resources> 
    <ProxyClass Data={Binding} x:Key="BindingProxy"/> 

</Window.Resources> 
... 
<MenuItem Command="{Binding Source={StaticResource BindingProxy}, Path=Data.MyDesiredCommand"/> 
... 
</Window> 

Was geschieht?
Data Eigenschaft ProxyClass binden an DataContext von Window, dann ist es alle Ihre comamnds und Eigenschaften Ihres ViewModel innerhalb der ProxyClass Ressource hat.
ein weiterer Vorteil dieses Ansatzes ist die Portabilität und Wiederverwenden in mehreren Ansichten und Projekten.

2

Per unten:
PlacementTarget ist das Steuerelement, das das ContextMenu (ex: DataGrid) besitzt. Keine Notwendigkeit für eine "Tag" -Eigenschaft.

IsEnabled bindet an den "myProperty" Wert des Datagrid.

Getestet habe ich diese und es funktioniert. Hatte ähnliches Problem mit der Bindung.

<ContextMenu 
DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}" 
IsEnabled="{Binding myProperty}" 
>