0

The issue seems to lie in the fact that ContextMenu is an orphaned child by design and has not visual or logical parent elements, i've tried using the PlacementTarget to set the DataContext but with no luck.

<DataTemplate x:Key="ODIF.Device">
        <Button HorizontalContentAlignment="Stretch" Background="WhiteSmoke" Padding="10,1" ContextMenuService.Placement="Right" VerticalContentAlignment="Stretch" Tag="{Binding ElementName=page}">
            <Button.BorderBrush>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FFC9C9C9" Offset="1"/>
                    <GradientStop Color="WhiteSmoke" Offset="0"/>
                </LinearGradientBrush>
            </Button.BorderBrush>
            <i:Interaction.Behaviors>
                <local:DropDownButtonBehavior/>
            </i:Interaction.Behaviors>
            <Button.ContextMenu>
                <ContextMenu ItemTemplate="{StaticResource ODIF.Channel}" DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget}">
                    <ContextMenu.Style>
                        <Style TargetType="ContextMenu">
                            <Style.Triggers>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <!--<Condition Binding="{Binding Converter={StaticResource TypeOfConverter}}" Value="{x:Type ODIF:InputDevice}" />-->
                                        <Condition Binding="{Binding inputDevicesInputChannelsVisible, ElementName=page}" Value="True" />
                                        <Condition Binding="{Binding inputDevicesOutputChannelsVisible, ElementName=page}" Value="True" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <MultiBinding>
                                                    <MultiBinding.Converter>
                                                        <local:CompositeCollectionConverter/>
                                                    </MultiBinding.Converter>
                                                    <Binding Path="InputChannels"/>
                                                    <Binding Path="OutputChannels"/>
                                                </MultiBinding>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <!--<Condition Binding="{Binding Converter={StaticResource TypeOfConverter}}" Value="{x:Type ODIF:InputDevice}" />-->
                                        <Condition Binding="{Binding inputDevicesInputChannelsVisible, ElementName=page}" Value="False" />
                                        <Condition Binding="{Binding inputDevicesOutputChannelsVisible, ElementName=page}" Value="True" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <Binding Path="OutputChannels"/>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <!--<Condition Binding="{Binding Converter={StaticResource TypeOfConverter}}" Value="{x:Type ODIF:InputDevice}" />-->
                                        <Condition Binding="{Binding inputDevicesInputChannelsVisible, ElementName=page}" Value="True" />
                                        <Condition Binding="{Binding inputDevicesOutputChannelsVisible, ElementName=page}" Value="False" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <Binding Path="InputChannels"/>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>

                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <!--<Condition Binding="{Binding Converter={StaticResource TypeOfConverter}}" Value="{x:Type ODIF:OutputDevice}" />-->
                                        <Condition Binding="{Binding outputDevicesInputChannelsVisible, ElementName=page}" Value="True" />
                                        <Condition Binding="{Binding outputDevicesOutputChannelsVisible, ElementName=page}" Value="True" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <MultiBinding>
                                                    <MultiBinding.Converter>
                                                        <local:CompositeCollectionConverter/>
                                                    </MultiBinding.Converter>
                                                    <Binding Path="InputChannels"/>
                                                    <Binding Path="OutputChannels"/>
                                                </MultiBinding>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <!--<Condition Binding="{Binding Converter={StaticResource TypeOfConverter}}" Value="{x:Type ODIF:OutputDevice}" />-->
                                        <Condition Binding="{Binding outputDevicesInputChannelsVisible, ElementName=page}" Value="False" />
                                        <Condition Binding="{Binding outputDevicesOutputChannelsVisible, ElementName=page}" Value="True" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <Binding Path="OutputChannels"/>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <!--<Condition Binding="{Binding Converter={StaticResource TypeOfConverter}}" Value="{x:Type ODIF:OutputDevice}" />-->
                                        <Condition Binding="{Binding outputDevicesInputChannelsVisible, ElementName=page}" Value="True" />
                                        <Condition Binding="{Binding outputDevicesOutputChannelsVisible, ElementName=page}" Value="False" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <Binding Path="InputChannels"/>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>
                            </Style.Triggers>
                        </Style>
                    </ContextMenu.Style>
                    <!--<ContextMenu.ItemsSource>
                        <MultiBinding>
                            <MultiBinding.Converter>
                                <local:CompositeCollectionConverter/>
                            </MultiBinding.Converter>
                            <Binding Path="InputChannels"/>
                            <Binding Path="OutputChannels"/>
                        </MultiBinding>
                    </ContextMenu.ItemsSource>-->
                    <ContextMenu.ItemContainerStyle>
                        <Style TargetType="{x:Type MenuItem}">
                            <Setter Property="Template" Value="{StaticResource NoIconColumnMenuItem}">
                            </Setter>
                            <EventSetter Event="Click" Handler="ChannelClick"/>
                        </Style>
                    </ContextMenu.ItemContainerStyle>
                </ContextMenu>
            </Button.ContextMenu>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Image Width="32" Height="32" Source="{Binding StatusIcon}" Grid.RowSpan="2" RenderOptions.BitmapScalingMode="HighQuality"/>
                <TextBlock Grid.Column="1" Text="{Binding DeviceName}" FontWeight="Bold" FontSize="13.333" Foreground="#FF0F0970"/>
                <TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding}"/>
                <Button Grid.Column="2" Content="X" Visibility="{Binding isImplicitlyRemoveable, Converter={StaticResource BoolToVisibilityConverter}}" Click="RemoveDevice" HorizontalAlignment="Right" VerticalAlignment="Top" Background="#FFF08F8F" BorderBrush="#FFBD4848" Foreground="White" FontWeight="Bold" Padding="2,0"/>
            </Grid>
        </Button>
    </DataTemplate>

The error is alwayse:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=page'. BindingExpression:Path=outputDevicesInputChannelsVisible; DataItem=null; target element is 'ContextMenu' (Name=''); target property is 'NoTarget' (type 'Object')

Which is due to ElementName not being able to crawl up the logical or visual tree from the context menu.

Im close to just 86'ing the context menu and re designing it to use a normal Menu, but figured i'd give SO a crack at it first.

Modified based on the comment below. This is almost working, however the conditional bindings that follow this format <Condition Binding="{Binding Path=DataContext,Converter={StaticResource TypeOfConverter},RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="{x:Type ODIF:OutputDevice}" /> are not working, they are needed to check the Buttons bound data

    <DataTemplate x:Key="ODIF.Device">
        <Button HorizontalContentAlignment="Stretch" Background="WhiteSmoke" Padding="10,1" ContextMenuService.Placement="Right" VerticalContentAlignment="Stretch" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Page}}}">
            <Button.BorderBrush>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FFC9C9C9" Offset="1"/>
                    <GradientStop Color="WhiteSmoke" Offset="0"/>
                </LinearGradientBrush>
            </Button.BorderBrush>
            <i:Interaction.Behaviors>
                <local:DropDownButtonBehavior/>
            </i:Interaction.Behaviors>

            <Button.ContextMenu>
                <ContextMenu ItemTemplate="{StaticResource ODIF.Channel}" DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                    <ContextMenu.Style>
                        <Style TargetType="ContextMenu">
                            <Style.Triggers>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <Condition Binding="{Binding Path=DataContext,Converter={StaticResource TypeOfConverter},RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="{x:Type ODIF:InputDevice}" />
                                        <Condition Binding="{Binding inputDevicesInputChannelsVisible}" Value="True" />
                                        <Condition Binding="{Binding inputDevicesOutputChannelsVisible}" Value="True" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <MultiBinding>
                                                    <MultiBinding.Converter>
                                                        <local:CompositeCollectionConverter/>
                                                    </MultiBinding.Converter>
                                                    <Binding Path="DataContext.InputChannels" RelativeSource="{RelativeSource AncestorType={x:Type Button}}"/>
                                                    <Binding Path="DataContext.OutputChannels" RelativeSource="{RelativeSource AncestorType={x:Type Button}}"/>
                                                </MultiBinding>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <Condition Binding="{Binding Path=DataContext,Converter={StaticResource TypeOfConverter},RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="{x:Type ODIF:InputDevice}" />
                                        <Condition Binding="{Binding inputDevicesInputChannelsVisible}" Value="False" />
                                        <Condition Binding="{Binding inputDevicesOutputChannelsVisible}" Value="True" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <Binding Path="DataContext.OutputChannels" RelativeSource="{RelativeSource AncestorType={x:Type Button}}"/>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <Condition Binding="{Binding Path=DataContext,Converter={StaticResource TypeOfConverter},RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="{x:Type ODIF:InputDevice}" />
                                        <Condition Binding="{Binding inputDevicesInputChannelsVisible}" Value="True" />
                                        <Condition Binding="{Binding inputDevicesOutputChannelsVisible}" Value="False" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <Binding Path="DataContext.InputChannels" RelativeSource="{RelativeSource AncestorType={x:Type Button}}"/>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>

                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <Condition Binding="{Binding Path=DataContext,Converter={StaticResource TypeOfConverter},RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="{x:Type ODIF:OutputDevice}" />
                                        <Condition Binding="{Binding outputDevicesInputChannelsVisible}" Value="True" />
                                        <Condition Binding="{Binding outputDevicesOutputChannelsVisible}" Value="True" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <MultiBinding>
                                                    <MultiBinding.Converter>
                                                        <local:CompositeCollectionConverter/>
                                                    </MultiBinding.Converter>
                                                    <Binding Path="DataContext.InputChannels" RelativeSource="{RelativeSource AncestorType={x:Type Button}}"/>
                                                    <Binding Path="DataContext.OutputChannels" RelativeSource="{RelativeSource AncestorType={x:Type Button}}"/>
                                                </MultiBinding>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <Condition Binding="{Binding Path=DataContext,Converter={StaticResource TypeOfConverter},RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="{x:Type ODIF:OutputDevice}" />
                                        <Condition Binding="{Binding outputDevicesInputChannelsVisible}" Value="False" />
                                        <Condition Binding="{Binding outputDevicesOutputChannelsVisible}" Value="True" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <Binding Path="DataContext.OutputChannels" RelativeSource="{RelativeSource AncestorType={x:Type Button}}"/>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <Condition Binding="{Binding Path=DataContext,Converter={StaticResource TypeOfConverter},RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="{x:Type ODIF:OutputDevice}" />
                                        <Condition Binding="{Binding outputDevicesInputChannelsVisible}" Value="True" />
                                        <Condition Binding="{Binding outputDevicesOutputChannelsVisible}" Value="False" />
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.Setters>
                                        <Setter Property="ItemsSource">
                                            <Setter.Value>
                                                <Binding Path="DataContext.InputChannels" RelativeSource="{RelativeSource AncestorType={x:Type Button}}"/>
                                            </Setter.Value>
                                        </Setter>
                                    </MultiDataTrigger.Setters>
                                </MultiDataTrigger>
                            </Style.Triggers>
                        </Style>
                    </ContextMenu.Style>
                    <!--<ContextMenu.ItemsSource>
                        <MultiBinding>
                            <MultiBinding.Converter>
                                <local:CompositeCollectionConverter/>
                            </MultiBinding.Converter>
                            <Binding Path="InputChannels"/>
                            <Binding Path="OutputChannels"/>
                        </MultiBinding>
                    </ContextMenu.ItemsSource>-->
                    <ContextMenu.ItemContainerStyle>
                        <Style TargetType="{x:Type MenuItem}">
                            <Setter Property="Template" Value="{StaticResource NoIconColumnMenuItem}">
                            </Setter>
                            <EventSetter Event="Click" Handler="ChannelClick"/>
                        </Style>
                    </ContextMenu.ItemContainerStyle>
                </ContextMenu>
            </Button.ContextMenu>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Image Width="32" Height="32" Source="{Binding StatusIcon}" Grid.RowSpan="2" RenderOptions.BitmapScalingMode="HighQuality"/>
                <TextBlock Grid.Column="1" Text="{Binding DeviceName}" FontWeight="Bold" FontSize="13.333" Foreground="#FF0F0970"/>
                <TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding}"/>
                <Button Grid.Column="2" Content="X" Visibility="{Binding isImplicitlyRemoveable, Converter={StaticResource BoolToVisibilityConverter}}" Click="RemoveDevice" HorizontalAlignment="Right" VerticalAlignment="Top" Background="#FFF08F8F" BorderBrush="#FFBD4848" Foreground="White" FontWeight="Bold" Padding="2,0"/>
            </Grid>
        </Button>
    </DataTemplate>
Wobbles
  • 3,033
  • 1
  • 25
  • 51
  • 2
    See [here](http://stackoverflow.com/questions/3668654/relativesource-binding-from-a-tooltip-or-contextmenu) and [here](http://stackoverflow.com/questions/26359091/context-menu-binding-to-parent-windows-datacontext) for some examples of bindings with ContextMenus – Gordon Allocman Mar 24 '16 at 15:39
  • @GordonAllocman The former got rid of the errors, but broke the ItemsSource binding. How should I modify the elements to point back to the Button as its binding parent? – Wobbles Mar 24 '16 at 15:49
  • 1
    Use the PlacementTarget.Tag wherever you need to bind to Page's context, remove it from the contextmenu's binding then the contextmenu's context should still be button's context, while the bindings you need to walk up the tree will have page's context – Gordon Allocman Mar 24 '16 at 15:58
  • @GordonAllocman I believe that is how I have it in the 2nd set of code I posted above. however `` and `` are no longer working – Wobbles Mar 24 '16 at 16:02
  • @GordonAllocman Ok, think I get what you are saying, `` seems to work now, now all I have to do is get it to work with the commented out condition and it should be good to go. – Wobbles Mar 24 '16 at 16:08
  • @GordonAllocman I expected this to work `` but it does not – Wobbles Mar 24 '16 at 16:14
  • The Condition tag will already have context of the button, so unless that has a property DataContext that won't work. an empty path will be a binding to the DataContext of the button already.You can look at the databinding errors to see what the current context is and use that to determine what path you need to get to your desired property – Gordon Allocman Mar 24 '16 at 16:44
  • How is that possible when the other Conditions are using the Pages context, I must point it somehow. I did try anyway however and no joy. – Wobbles Mar 24 '16 at 16:50
  • You want to use the placement tag at the lowest possible point each time, keeping your main context as the button's context – Gordon Allocman Mar 24 '16 at 16:51
  • nahh, no joy, and it appears that what I originally thought was working is infact not, the Buttons Tag is not storing the ancestor type either, so it appears the answers in those link will NOT solve this issue. – Wobbles Mar 24 '16 at 17:34

0 Answers0