Walter Williams
Walter Williams

Reputation: 974

Different behavior within RibbonApplicationMenu commands

I have a RibbonApplicationMenu in my app similar to this example:

<RibbonApplicationMenu>
    <RibbonApplicationMenuItem Header="Open Project..." Command="{Binding OpenProjectCommand}" />
    <RibbonApplicationMenuItem Header="Save Project..." Command="{Binding SaveProjectCommand}" />
    <RibbonApplicationMenuItem Header="Exit" Command="{Binding CloseWindowCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type RibbonWindow}}}" />
    <RibbonApplicationMenu.FooterPaneContent>
        <RibbonButton Label="Exit" Command="{Binding CloseWindowCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type RibbonWindow}}}" />
    </RibbonApplicationMenu.FooterPaneContent>
</RibbonApplicationMenu>

private void CloseWindow (Object parameter)
{
    ((Window) parameter).Close();
}

In the example there are a RibbonApplicationMenuItem and RibbonButton item bound to the same command and having the same parameter passed. The command executes the CloseWindow() function. What I find curious is that when the RibbonApplicationMenuItem is clicked, the parameter to the function is the pointer to the RibbonWindow. However, when the RibbonButton is clicked, the parameter to the function is null.

Why would the behavior be different?

Upvotes: 1

Views: 547

Answers (1)

Dusan
Dusan

Reputation: 411

Setting FooterPaneContent to be another control (RibbonButton) messes up the logical tree that's why RelativeAncestor doesn't work.

In the other words even if you bind to the button itself, traversing with LogicalTreeHelper won't work (VisualTreeHelper won't work either since the pane is a PopUp and lives in a separate visual tree):

<r:RibbonApplicationMenu.FooterPaneContent>
    <r:RibbonButton Label="Exit" Command="{Binding CloseWindowCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}" />
</r:RibbonApplicationMenu.FooterPaneContent>
private void CloseWindow(object parameter)
{
    RibbonButton _button = (RibbonButton)parameter;

    // _appMenu will be null
    DependencyObject _appMenu = LogicalTreeHelper.GetParent(_button);
}

So, your options are:

  1. Bind to self and use _button.Ribbon property to get the Ribbon and traverse up the logical tree to get the RibbonWindow.

  2. Set ContentTemplate instead of Content. Be careful to propagate the DataContext though.

<r:RibbonApplicationMenu.FooterPaneContentTemplate>
    <DataTemplate>
        <r:RibbonButton Label="Exit" DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type r:RibbonApplicationMenu}}, Path=DataContext}" Command="{Binding Path=CloseWindowCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type r:RibbonWindow}}}" />
    </DataTemplate>
</r:RibbonApplicationMenu.FooterPaneContentTemplate>
   private void CloseWindow(object parameter)
   {
        ((Window)parameter).Close();
   }

Upvotes: 1

Related Questions