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>