Search code examples
wpfdatatemplatemenuitemdatatrigger

Change MenuItem header and icon based on viewmodel property binding


I cannot figure out how to do this, and one would think it would be pretty simple.

I have a MenuItem that's part of a ContextMenu. I have a binding to a boolean property on a viewmodel. Depending on the state of this property, I want the MenuItem's header text and icon to change.

I could certainly use an IValueConverter for this, but I'm sure that there is a more elegant solution using a DataTemplate and triggers. I just can't figure out the proper markup.

The code I worked up (snipped below) has two problems: one the HeaderTemplate doesn't appear to contain the icon, so what would be the MenuItems's text contains the icon as well (normally the icon appears on in left hand section - see image and compare with the Copy and Clear menuitems). Additionally, clicking the MenuItem doesn't trigger the DataTemplate changes (note the command works, the viewmodel binding does in fact toggle the true/false state).

   <ContextMenu>
            <MenuItem Command="{Binding Source={x:Static cmd:Commands.PauseCommand}}"
                      CommandParameter="{Binding}">
                <MenuItem.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Image x:Name="img" Source="../Icons/pause.png"/>
                            <TextBlock x:Name="txt" Text="Pause"/>
                        </StackPanel>
                        <DataTemplate.Triggers>
                            <DataTrigger Binding="{Binding IsPaused}" Value="True" >
                                <Setter Property="Image.Source" Value="../Icons/play.png" TargetName="img"/>
                                <Setter Property="Text" Value="Play" TargetName="txt"/>
                            </DataTrigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
                </MenuItem.HeaderTemplate>
            </MenuItem>

MenuItem


Solution

  • You mean like this? Dont make things harder than they are ;)

    <ContextMenu>
                            <MenuItem Command="{Binding Source={x:Static cmd:Commands.PauseCommand}}"
                      CommandParameter="{Binding}">
                                <MenuItem.Style>
                                    <Style TargetType="MenuItem">
                                        <Setter Property="Icon" Value="../Icons/play.png>"></Setter>
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding IsPaused, Mode=OneWay}" Value="True">
                                                <Setter Property="Icon" Value="../Icons/pause.png"></Setter>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </MenuItem.Style>
                            </MenuItem>
                        </ContextMenu>