0
votes

I am trying to bind to command that is on my viewmodel. I am using an event trigger that is way down on the visual tree. I have tried many variations of RelativeSource, FindAncestor and AncestorType trying to bind to it. Every time I get a bind path expression error.

This is my xaml document outline:

<Window>
   <Grid>
      <GridView>
         <HierarchyChildTemplate>
             <DataTemplate>
                  <TabControl>
                      <TabItem>
                          <GridView>
                              <RowDetailsTemplate>
                                 <TabControl>
                                     <!--trying to bind a event trigger here to a command on the viewModel -->

Here is an example of the binding I've tried:

<i:Interaction.Triggers>
      <i:EventTrigger EventName="SelectionChanged">
          <i:InvokeCommandAction Command="{Binding Path=SelectionChangedCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}"/>
      </i:EventTrigger>
</i:Interaction.Triggers>

How would I bind to this command from the location noted in the xaml?

2
Did you try Path=DataContext.SelectionChangedCommand instead of just SelectionChangedCommand?Blachshma
Yes. That does get me a different result...it will get me onto the DataContext of the first GridView (A model in the collection bound the GridView) but not to the DataContext of the ViewModel.David Oesterreich
I don't believe that would work simply because the triggers actually aren't in the visual tree. RelativeSource bindings walk the visual tree, which is hard to do when you're not in it. Try switching the relative source for a named element, such as in the second part of @Blachshma's answer.user1228

2 Answers

0
votes

Based on your visual tree and what you wrote in the comments (I haven't tested it):

<i:Interaction.Triggers>
  <i:EventTrigger EventName="SelectionChanged">
      <i:InvokeCommandAction Command="{Binding Path=DataContext.SelectionChangedCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
  </i:EventTrigger>
</i:Interaction.Triggers>

That said, I recommend in this case to use a Named binding.... Give a name to the topmost grid (or to the original window), e.g.:

<Window Name="MainWindow">
  ....

Then, you can Bind using ElementName :

<i:InvokeCommandAction Command="{Binding Path=DataContext.SelectionChangedCommand, 
                                         ElementName=MainWindow}"/>

Regarding what you said in your comments (that AncestorType is reaching the wrong grid), using AncestorLevel=2 should help you bind to the topmost Grid.

0
votes

Ended up trying this and it worked:

<i:Interaction.Triggers>
  <i:EventTrigger EventName="SelectionChanged">
     <i:InvokeCommandAction Command="{Binding Path=DataContext.SelectionChangedCommand, 
         RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=2,AncestorType={x:Type GridView}}}"/>
   </i:EventTrigger>
</i:Interaction.Triggers>     

Key points here are Prefacing the command with DataContext and AncestorLevel=2.