I have a customized menu with an ItemsSource bound to a ObservableCollection in my view model. To customize the menu, I'm using a ControlTemplate in the style and the ControlTemplate contains a label. I would like to show or hide this label depending on the IsDefault
property in my MenuItem
class.
Here's the simplified xaml:
<Menu x:Name="RewriteMenu" ItemsSource="{Binding RewriteMenuItems}"Margin="0,10,10,0" >
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Name}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border x:Name="Border" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1"
CornerRadius="6">
<Grid Margin="0,0,0,0" Background="{TemplateBinding Background}"
VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Col0" MinWidth="17" Width="Auto"
SharedSizeGroup="MenuItemIconColumnGroup" />
<ColumnDefinition Width="Auto"
SharedSizeGroup="MenuTextColumnGroup" />
<ColumnDefinition Width="Auto"
SharedSizeGroup="MenuItemIGTColumnGroup" />
<ColumnDefinition x:Name="Col3" Width="150" />
<ColumnDefinition x:Name="Col4" Width="Auto" />
</Grid.ColumnDefinitions>
<!--ContentPresenter to show an Icon if needed-->
<ContentPresenter Grid.Column="0" Margin="14,0,6,0" x:Name="Icon" VerticalAlignment="Center" ContentSource="Icon" Width="18" Height="18" />
<!--Content for the menu text etc-->
<TextBlock Height="27" FontFamily="{StaticResource PoppinsRegular}" VerticalAlignment="Center" Width="260" Grid.Column="1" x:Name="HeaderHost"
Text="{TemplateBinding Header}" />
<Label Grid.Column="2" Style="{StaticResource DefaultVoiceStyle}" Background="#BFCBFF" Visibility="{Binding Content.IsDefault, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource InverseBoolToVisConverter}}"/>
<
</Style>
</Menu.ItemContainerStyle>
<Menu.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" Width="340" />
</ItemsPanelTemplate>
</Menu.ItemsPanel>
</Menu>
I found this answer so I tried something like: <Label Visibility="{Binding Content.IsDefault, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource InverseBoolToVisConverter}}"/>
but this binding only gets me to the MenuItem (the WPF version, not my custom class. Sorry, poor naming on my part) and I can't bind to the IsDefault
property.
Is this possible? Is there a better way?
I tried to make a custom MenuItem that inherits from System.Windows.Controls.MenuItem
:
public class VoiceRewriteMenuItem : MenuItem
{
public bool IsDefault
{
get { return (bool)GetValue(IsDefaultProperty); }
set { SetValue(IsDefaultProperty, value); }
}
// Using a DependencyProperty as the backing store for IsDefault. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsDefaultProperty =
DependencyProperty.Register("IsDefault", typeof(bool), typeof(VoiceRewriteMenuItem), new PropertyMetadata(false));
}
This allows me to bind to my property but now the menu doesn't appear. Any thoughts?
I managed to find a work around. In System.Windows.Control.MenuItem
there are a few boolean properties that I don't care about in this case. I bound the IsChecked
property to my IsDefault
property in my view model and set the label visibility to visible only if MenuItem.IsChecked
is true. So it works like this:
<Menu x:Name="RewriteMenu" ItemsSource="{Binding RewriteMenuItems}"Margin="0,10,10,0" >
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Name}" />
<Setter Property="IsChecked" Value="{Binding IsDefault}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border x:Name="Border" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1"
CornerRadius="6">
<Grid Margin="0,0,0,0" Background="{TemplateBinding Background}"
VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Col0" MinWidth="17" Width="Auto"
SharedSizeGroup="MenuItemIconColumnGroup" />
<ColumnDefinition Width="Auto"
SharedSizeGroup="MenuTextColumnGroup" />
<ColumnDefinition Width="Auto"
SharedSizeGroup="MenuItemIGTColumnGroup" />
<ColumnDefinition x:Name="Col3" Width="150" />
<ColumnDefinition x:Name="Col4" Width="Auto" />
</Grid.ColumnDefinitions>
<!--ContentPresenter to show an Icon if needed-->
<ContentPresenter Grid.Column="0" Margin="14,0,6,0" x:Name="Icon" VerticalAlignment="Center" ContentSource="Icon" Width="18" Height="18" />
<!--Content for the menu text etc-->
<TextBlock Height="27" FontFamily="{StaticResource
PoppinsRegular}"
VerticalAlignment="Center" Width="260"
Grid.Column="1" x:Name="HeaderHost"
Text="{TemplateBinding Header}" />
<Label Grid.Column="2" Style="{StaticResource DefaultVoiceStyle}" Background="#BFCBFF" Visibility="{Binding Content.IsChecked, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisConverter}}"/>
</Style>
</Menu.ItemContainerStyle>
<Menu.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" Width="340" />
</ItemsPanelTemplate>
</Menu.ItemsPanel>
</Menu>
It's not the elegant binding solution I was looking for but it works.