0

I am trying to bind to an element from a context menu inside a drop-down menu button (from http://shemesh.wordpress.com/2011/10/27/wpf-menubutton/). Even though outside the context menu the binding seems to work, the binding inside the context menu does not.

This is the XAML (very simplified):

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" CanContentScroll="False">
            <ListBox x:Name="lbScenarios"  HorizontalContentAlignment="Stretch">
                <ItemsControl.Template>
                    <ControlTemplate TargetType="ItemsControl">
                        <ItemsPresenter Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualWidth}"/>
                    </ControlTemplate>
                </ItemsControl.Template>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Border>
                            <Expander>
                                <Expander.Header>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto" />
                                            <ColumnDefinition Width="Auto" />
                                            <ColumnDefinition Width="Auto" />
                                            <ColumnDefinition Width="Auto" />
                                            <ColumnDefinition Width="*" />
                                        </Grid.ColumnDefinitions>
                                        <TextBlock Margin="5,0,0,0" Grid.Column="0" VerticalAlignment="Center">Results</TextBlock>
                                        <local:MenuButton Grid.Column="3" Content="Menu" Margin="5,0,0,0" VerticalAlignment="Center">
                                            <local:MenuButton.Menu>
                                                <ContextMenu>
                                                    <MenuItem Header="Save pie chart as image"
                                                                              Command="{Binding SaveChartImageCommand}"
                                                                              CommandParameter="{Binding ElementName=pieChart}" />
                                                    <MenuItem Header="Save bar chart as image"
                                                                              Command="{Binding SaveChartImageCommand}"
                                                                              CommandParameter="{Binding ElementName=barChart}" />
                                                </ContextMenu>
                                            </local:MenuButton.Menu>
                                        </local:MenuButton>
                                    </Grid>
                                </Expander.Header>
                                <Expander.Content>
                                    <StackPanel>
                                        <Image x:Name="pieChart" />
                                        <Image x:Name="barChart" />
                                    </StackPanel>
                                </Expander.Content>
                            </Expander>
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ListBox>
        </ScrollViewer>
    </Grid>
</Window>

The binding that does not work is the {Binding ElementName=pieChart}, which is funny because the command is being found. I couldn't seem to get a RelativeSource to work, but can someone help me with getting the binding correct?

Walter Williams
  • 944
  • 3
  • 11
  • 25
  • 2
    Very similar question - http://stackoverflow.com/questions/1013558/elementname-binding-from-menuitem-in-contextmenu. – Eugene Podskal Aug 22 '14 at 17:25
  • I have tried to apply the solutions in that question, but there are two major differences: the context menu occurs in a data template, and there are multiple things being bound to in the menu (either the pie chart or the bar chart -- I edited the question to reflect his). – Walter Williams Aug 22 '14 at 17:45
  • But there are some solutions that work even with templates. And you can always move some view data into the model and reference it through datacontext (well, it may partially violate the MVVM structure, but nonetheless). – Eugene Podskal Aug 22 '14 at 18:06

1 Answers1

5

Since ContextMenu doesn't lie in same Visual tree as that of its placement target so ElementName binding won't work because it requires both controls to be in same Visual tree.

Try using x:Reference which doesn't have this constraint of to be in same visual tree.

CommandParameter="{Binding Source={x:Reference pieChart}}"

OR

use it like this

CommandParameter="{x:Reference pieChart}"

Note - x:Reference will be found in WPF 4.0 or later.

Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
  • I tried this and got a XamlParseException "Two-way binding requires Path or XPath." I also tried it with Mode=OneWay, Mode=OneWayToSource and Mode=OneTime. None worked. – Walter Williams Aug 22 '14 at 18:20
  • `CommandParameter` is not a two way binding. Works fine at my end. However, you can try this as well - `CommandParameter="{x:Reference pieChart}"`. – Rohit Vats Aug 22 '14 at 18:23