wpf menuitem style.trigger - wpf

I am trying to implement a checkable menu, where only one menuitem is checked at a time, i.e. radio button behavior. I would like to achieve this with a style and datatriggers to keep it in xaml. The intention is to observe the other items; whenever any other is true, it should be set to false. Indeed, only one is checked at a time, however two button presses are required. How can I make it work with just one button press?
<MenuItem Header="Header">
<MenuItem x:Name="ChangesMenuItem" Header="Changes" IsCheckable="True" Command="{Binding ViewChangesCommand}">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=SettingsMenuItem, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=SyncMenuItem, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
<MenuItem x:Name="SettingsMenuItem" Header="Settings" IsCheckable="True" Command="{Binding ViewSettingsCommand}">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ChangesMenuItem, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=SyncMenuItem, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
<MenuItem x:Name="SyncMenuItem" Header="Sync" IsCheckable="True" Command="{Binding ViewSyncCommand}">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ChangesMenuItem, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=SettingsMenuItem, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
</MenuItem>

I have a header which changes according to the selection, so I decided to bind to that property.
<Menu>
<MenuItem Header="{Binding Header}">
<MenuItem x:Name="ChangesMenuItem" Header="Changes" IsCheckable="True" Command="{Binding ViewChangesCommand}">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Setter Property="IsChecked" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Header}" Value="Changes">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
<MenuItem x:Name="SettingsMenuItem" Header="Settings" IsCheckable="True" Command="{Binding ViewSettingsCommand}">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Setter Property="IsChecked" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Header}" Value="Settings">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
<MenuItem x:Name="SyncMenuItem" Header="Sync" IsCheckable="True" Command="{Binding ViewSyncCommand}">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Setter Property="IsChecked" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Header}" Value="Sync">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
</MenuItem>
</Menu>

Related

selected row color on DataGrid not appear above the cells

According to this picture the color of the selected row does not appear over the cells that have been changed color by Style, but appears in the cells that have not been colored by style
i want to set it over the cells that have been changed color by Style
<DataGridTextColumn Header=" 8 --- 7 " Binding="{Binding From_7_To_8}">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}" >
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<CheckBox x:Name="C8" Click="CHECK_CLICK"
Style="{DynamicResource CheckBoxStyle1}"
IsEnabled="{Binding Converter={StaticResource IsEnabled_Cell},ConverterParameter=C8}"
IsChecked="{Binding From_7_To_8,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
FontSize="12" Content=" 7 --- 8 "
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
FlowDirection="LeftToRight"
HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
</CheckBox>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Content.IsChecked, RelativeSource={RelativeSource Self}}"
Value="false" >
<Setter Property="Background" Value="{x:Null}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Order_Life_7_8,Mode=TwoWay}" Value="0">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Order_Life_7_8,Mode=TwoWay}" Value="1">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
<DataTrigger Binding="{Binding Order_Life_7_8,Mode=TwoWay}" Value="2">
<Setter Property="Background" Value="GreenYellow"/>
</DataTrigger>
<DataTrigger Binding="{Binding Order_Life_7_8,Mode=TwoWay}" Value="3">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>

Binding #items of a MenuItem to visibility in a CompositeCollection

I have a MenuItem that is populated via an ObservableCollection plus one static MenuItem that i want to display only if the collection is empty.
To do that i am using CompositeCollection, and try to trigger the visibility of the MenuItem via DataTrigger but to no avail.
No matter if i use HasItems or Items.Count, the binding itself seems to be the problem:
<MenuItem x:Name="ClientsList" Header="Clients">
<MenuItem.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={x:Static win32:ClientProcessHandler.ClientProcessList}}" />
<MenuItem Header="No Client.." IsEnabled="False">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Style.Triggers>
<!-- Here is the binding -->
<DataTrigger Binding="{Binding Items.Count, ElementName=ClientsList}" Value="2">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
</CompositeCollection>
</MenuItem.ItemsSource>
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="IsChecked" Value="{Binding IsSelected, Mode=OneWay}" />
<Setter Property="Header" Value="{Binding Path}" />
<Setter Property="Command" Value="{Binding DataContext.SelectClient, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
<Setter Property="CommandParameter" Value="{Binding }" />
<Setter Property="StaysOpenOnClick" Value="True" />
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
Bind to the Count property of the source collection:
<DataTrigger Binding="{Binding Count,
Source={x:Static win32:ClientProcessHandler.ClientProcessList}}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>

CheckBox text to change based on its IsChecked

I want a CheckBox text to changed based on the IsChecked status.
Tried with the following, but it complains about not having the property Content
<CheckBox Name="IsManualInput" IsChecked="{Binding Path=IsManual, Mode=TwoWay}" >
<CheckBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}" Value="True" >
<Setter Property="Content" Value="Manual" />
<Setter Property="IsReadOnly" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}" Value="True" >
<Setter Property="Content" Value="Define manually..." />
<Setter Property="IsReadOnly" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
It's a simple mistake, you need to include TargetType in your Style.
e.g.
<Style TargetType="{x:Type CheckBox}">

Style Trigger for different images and border background

I Want to use different Border Background and Different Images (each image must use different background color)
how i change use StyleTrigger to do it ? (Now it just show red border for all images)
<DataTemplate>
<Border BorderThickness="1" Width="18" Height="18" CornerRadius="2" BorderBrush="Red" Background="Red">
<Image Width="16" Height="16">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{x:Null}" />
<Style.Triggers>
<DataTrigger Binding="{Binding RowData.DataContext.my}" Value="High">
<Setter Property="Source" Value="/project;component/Images/High.png" />
</DataTrigger>
<DataTrigger Binding="{Binding RowData.DataContext.my}" Value="Medium">
<Setter Property="Source" Value="/project;component/Images/Medium.png" />
</DataTrigger>
<DataTrigger Binding="{Binding RowData.DataContext.my}" Value="Low">
<Setter Property="Source" Value="/project;component/Images/Low.png" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Border>
</DataTemplate>
Thank you.
Assuming that your Binding is correct, you just need to add a similar Style to the Border to update the Background property and remove the Background value from the Border itself:
<DataTemplate>
<Border BorderThickness="1" Width="18" Height="18" CornerRadius="2" BorderBrush="Red">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding RowData.DataContext.my}" Value="High">
<Setter Property="Background" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding RowData.DataContext.my}" Value="Medium">
<Setter Property="Background" Value="Blue" />
</DataTrigger>
<DataTrigger Binding="{Binding RowData.DataContext.my}" Value="Low">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Image Width="16" Height="16">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{x:Null}" />
<Style.Triggers>
<DataTrigger Binding="{Binding RowData.DataContext.my}" Value="High">
<Setter Property="Source" Value="/project;component/Images/High.png" />
</DataTrigger>
<DataTrigger Binding="{Binding RowData.DataContext.my}" Value="Medium">
<Setter Property="Source" Value="/project;component/Images/Medium.png" />
</DataTrigger>
<DataTrigger Binding="{Binding RowData.DataContext.my}" Value="Low">
<Setter Property="Source" Value="/project;component/Images/Low.png" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Border>
</DataTemplate>
Try this.

Changing Button image when IsEnabled

I want to change button image when button IsEnabled == False.
Below is my example, bindings are fine, when I change them for False/True it is still not working.
<Button x:Name="btnBackward" Grid.Column="0" Grid.Row="2" Command="{Binding UserWorkflowManager.NavigateBackward}" IsEnabled="{Binding UserWorkflowManager.NavigateBackwardEnable}" Grid.RowSpan="2">
<Button.Template>
<ControlTemplate>
<Image Name="_image" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="/UserWorkflow.View;component/Images/LDC500_butX_PreviousPane_norm.bmp" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=btnBackward, Path=IsEnabled}" Value="False">
<Setter Property="Source" Value="/UserWorkflow.View;component/Images/LDC500_butX_PreviousPane_dis.bmp"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</ControlTemplate>
</Button.Template>
</Button>
Try the following
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled,RelativeSource={RelativeSource AncestorType=Button}}" Value="False">
<Setter Property="Source" Value="/UserWorkflow.View;component/Images/LDC500_butX_PreviousPane_dis.bmp"/>
</DataTrigger>
</Style.Triggers>
Or add the trigger directly in the control template like so
<ControlTemplate>
<Image Name="_image" HorizontalAlignment="Center">
..........
</Image>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="_image" Property="Source" Value="/UserWorkflow.View;component/Images/LDC500_butX_PreviousPane_dis.bmp" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Try this:
<Button x:Name="btnBackward" Grid.Column="0" Click="btnBackward_Click">
<Button.Template>
<ControlTemplate>
<Image Name="_image" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="/Images/0.png" />
</Style>
</Image.Style>
</Image>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Source" Value="/Images/1.png" TargetName="_image"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
You should specify "TargetName" property for a setter within "ControlTemplate.Triggers"
The soution is is to use RelativeSource={RelativeSource Self}} in your DataTrigger.
<DataTrigger
Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}"
Value="False">
Example
Add this style:
<Style x:Key="MainButtonStyle" TargetType="Button" BasedOn="{StaticResource ChromelessButtonStyle}">
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Background" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}}" Value="False">
<Setter Property="Background" Value="Blue" />
</DataTrigger>
</Style.Triggers>
</Style>
Then apply this style to the button:
<Button x:Name="ActionButton" Style="{StaticResource MainButtonStyle}" Command="{Binding MyCmd}" IsEnabled="{Binding ActionButtonEnabled}"/>

Resources