Question

Qu'est-ce que je fais mal ici:

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

C'est juste un exemple simplifié, qui ne fonctionne pas de toute façon :) En fait, je dois obtenir une valeur d'une autre propriété qui est portée de DataContext de la fenêtre.

Aidez-moi svp.

Était-ce utile?

La solution

Ceci est délicat car infobulle ne fait pas partie du VisualTree. vous voyez une solution fraîche pour le même problème avec ContextMenus. De la même façon, vous pouvez aller pour l'info-bulle.

UPDATE Malheureusement, le lien a disparu et je n'ai pas trouvé le plus article référencé.
Pour autant que je me souvienne, le blog référencé a montré comment se lier à une DataContext d'un autre VisualTree, qui est souvent necessay lors de la liaison d'une info-bulle, un ContextMenu ou Popup.

Une façon agréable de ce faire, est de fournir l'instance désirée (par exemple ViewModel) dans le Tag-propriété du PlacementTarget. L'exemple suivant fait pour accéder à une instance de commande d'un ViewModel:

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

Je l'ai pas testé et son depuis longtemps je l'ai fait la dernière fois. S'il vous plaît faire un commentaire si cela ne fonctionne pas pour vous.

MISE À JOUR 2

Comme le lien d'origine que cette réponse a été écrit au sujet est allé, je frappé archive.org et trouvé entrée de blog d'origine. Ici, il est, mot pour mot du blog:

  

Parce qu'un ContextMenu dans WPF n'existe pas dans l'arbre visuel de   votre page / fenêtre / contrôle en soi, la liaison de données peut être un peu délicat.   J'ai cherché haut et bas sur le Web pour cela, et le plus   réponse commune semble être « juste le faire dans le code derrière ». FAUX! je   ne sont pas venus dans le monde merveilleux de XAML pour y retourner à   faire les choses dans le derrière de code.

     

Voici mon exemple qui vous permettra de se lier à une chaîne   existe en tant que propriété de la fenêtre.

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>
     

La partie importante est la balise sur le bouton (bien que vous pourriez aussi   facilement régler le DataContext du bouton). Cela stocke une référence à   la fenêtre parent. Le ContextMenu est capable d'accéder à cette   à travers elle la propriété de PlacementTarget. Vous pouvez ensuite passer ce contexte   vers le bas par vos éléments de menu.

     

Je reconnais ce n'est pas la solution la plus élégante du monde.   Cependant, il bat des trucs de réglage dans le derrière de code. Si quelqu'un a un   même meilleure façon de le faire, je serais ravi de l'entendre.

Autres conseils

Par ci-dessous:
PlacementTarget est le contrôle qui est propriétaire du ContextMenu (ex: DataGrid). Pas besoin d'une propriété « tag ».

isEnabled se fixe à la valeur "myProperty" du DataGrid.

Je l'ai testé cela et il fonctionne. Ayant été question similaire à la liaison.

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

Parce que ContextMenu n'est pas dans l'arbre visuel, la liaison ne fonctionnera pas. une solution simple, utilise modèle Proxy, vous pouvez créer une classe wrapper qui hérite de DependencyObject et a une DependencyProperty qui gardera un DataContext de votre Window, alors vous pouvez avoir une ressource de la procuration en XAML et enfin lier votre commande MenuItem à votre souhaitée commande via l'objet proxy.
Sample 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));

}

Comment utiliser en XAML:

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

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

Qu'est-ce qui se passe? propriété Data de ProxyClass se lie à DataContext de Window, il a tous vos comamnds et les propriétés de votre ViewModel dans la ressource ProxyClass.
Un autre avantage de cette approche est la portabilité et la réutilisation dans plusieurs vues et des projets.

Je pense que cela devrait être fait comme ceci:

{Binding Path=Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top