I have a WPF treeview, with nodes visibility dependent on their "Deleted" binding property:
<Style x:Name="SelectedTreeItem" TargetType="TreeViewItem">
<EventSetter Event="MouseRightButtonDown" Handler="TreeSetup_MouseRightButtonDown"/>
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding Deleted}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
I would like to make add some way to ignore this deleted property value. This would be achieved by a button "Show deleted items".
I do not want to change the "Deleted" value, but rather add a global condition to that forces this binding to ignore untill the button is pressed again.
You can do that via MultiDataTrigger.Conditions. Here is an example for visibility:
<Style>
<Setter Property="Control.Visibility" Value="Visible" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsPropA}" Value="false" />
<Condition Binding="{Binding Path=IsPropB}" Value="false" />
</MultiDataTrigger.Conditions>
<Setter Property="Control.Visibility" Value="Hidden" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
I used the other answer in conjuction with a static resource
<Style>
<Setter Property="Control.Visibility" Value="Visible" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsPropA}" Value="false" />
<Condition Binding="{Binding Source={StaticResource ClassName},Path=PropertyName}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Control.Visibility" Value="Hidden" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
Just had to create the local resource under Window resources:
<Window.Resources>
<local:ClassName x:Key="ClassName"/>
And then the button used to show deleted or not:
private void btnApply_Click(object sender, RoutedEventArgs e)
{
//ApplyGeneralChanges();
var item = this.FindResource("ClassName") as ClassName;
item.DisplayDeleted = !item.DisplayDeleted;
}
Related
I have a property in my ModularClientModule class called ExistsOnDisk. When that property is set to false, I want to disable the CheckBox. For some reason, this does not seem to work despite me putting it last in the Triggers XAML block, which means it should be the last thing to fire. I.e, nothing should be interfering. I know my code-behind should be correct because as you will see below, I have another control which receives the update and fires fine.
This one here responds to the ExistsOnDisk property change without issue, and strikesthrough the text:
GridViewColumn x:Name="FileNameHeader" Header="File Name">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:ModularClientModuleUI}">
<TextBlock Text="{Binding Filename}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ExistsOnDisk}" Value="False">
<Setter Property="TextDecorations" Value="Strikethrough"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
This one here does not, and the checkbox remains enabled:
<GridViewColumn x:Name="StatusHeader" Header="Status">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:ModularClientModuleUI}">
<StackPanel>
<CheckBox x:Name="ClientModuleStatusCheckBox" Margin="5, 0" Click="ClientModuleStatusCheckBox_Click" IsEnabled ="{Binding Client.Online}">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource MahApps.Styles.CheckBox}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding LoadState}" Value="Loaded">
<Setter Property="IsChecked" Value="True" />
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadState}" Value="Unloaded">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadState}" Value="Loading">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding ExistsOnDisk}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding ExistsOnDisk}" Value="False">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
What could be going on here?
Set the default value of the IsEnabled using a Setter and remove IsEnabled ="{Binding Client.Online}" from the <CheckBox> element:
<CheckBox x:Name="ClientModuleStatusCheckBox" Margin="5, 0" Click="ClientModuleStatusCheckBox_Click">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource MahApps.Styles.CheckBox}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding LoadState}" Value="Loaded">
<Setter Property="IsChecked" Value="True" />
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadState}" Value="Unloaded">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadState}" Value="Loading">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding ExistsOnDisk}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
Also note that you shouldn't use more than one trigger on the same bool property.
I need a button disabled untill 3 textboxes are empty and no selection is done on a combobox. I wrote the following XAML code:
<Button x:Name="previewBtn" Content="Anteprima" HorizontalAlignment="Left" Margin="164,33,0,0" VerticalAlignment="Top" Width="75" Height="19" Click="previewBtn_Click_1">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding Text.Length, ElementName=titleBox}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Text.Length, ElementName=StEpLabel}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Text.Length, ElementName=seasonBox}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedIndex, ElementName=cmb}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Binding to the textboes work but the combobox not. What should I write? Thanks
<DataTrigger Binding="{Binding SelectedIndex, ElementName=cmb}" Value="-1">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
SelectedIndex will be -1 when no item is selected.
I currently have another issue opened related to the DataGrid but I thought I'd open another
I'm trying to change the status of a checkbox automatically based on the value of another column, but how do I do this using the DataGridCheckBoxColumn? I was using the 'IsSelected' but eventually realized this property applied to the cell rather than the checkbox.
Here's my code
<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive}">
<DataGridCheckBoxColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="01" >
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" >
<Setter Property="IsSelected" Value="True" />
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="03" >
<Setter Property="IsSelected" Value="False" />
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridCheckBoxColumn.CellStyle>
</DataGridCheckBoxColumn>
As you can see, I want to select the checkbox automatically when the LocationText is 2 and unselect it when the LocationText is 3.
Any ideas?
Update 1:
I thought I figured it out when I tried the following:
<DataGridCheckBoxColumn.ElementStyle>
<Style TargetType="CheckBox">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="01" >
<Setter Property="IsChecked" Value="False" />
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" >
<Setter Property="IsChecked" Value="True" />
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="03" >
<Setter Property="IsChecked" Value="False" />
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridCheckBoxColumn.ElementStyle>
But to no avail. It disables the checkbox alright but it refuses to check it.
Frustrating...
it should be
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate >
<DataTemplate x:Name="dtAllChkBx">
<CheckBox Name="cbxAll">
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=wndMain, Path=LocationText , Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Value="" >
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=wndMain, Path=LocationText, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Value="01" >
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=wndMain, Path=LocationText, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Value="02" >
<Setter Property="IsChecked" Value="True" />
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=wndMain, Path=LocationText, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Value="03" >
<Setter Property="IsChecked" Value="False" />
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
and datacontext must be implement INotifyPropertyChanged
and when binded property changed it needs to notify property changed.
XAML :
<RadioButton x:Name="RadioButtonA">
<RadioButton.Style>
<Style TargetType="RadioButton">
<Setter Property="IsChecked" Value="{Binding Path=RadioAValue}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=CheckBoxA, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
C# Code behind
public bool RadioAValue
{
get
{
...
}
set
{
...
}
}
set section of RadioAvalue will not be called when CheckBoxA is checked.
Any reason why?
Problem in your code
You are setting the binding in Style Setter
<Setter Property="IsChecked" Value="{Binding Path=RadioAValue}" />
and on clicking the checkbox you have overwriting the Binding with the value False. Now there is no more Bindings over the element and it wont call the set anymore.
Also, if you try to bind it over the RadioButton itself instead of setters that will take more precedence and your Triggers won't work there.
Solution
I would recommend you to have Command binding over the Checkbox and update the value RadioAValue from your ViewModel
If you want conditional setter use MultiBinding, right now you block binding with already setted value
<Setter Property="IsChecked" Value="{Binding Path=RadioAValue}" />
Must be something like this (didn't test thought):
<RadioButton x:Name="YouRadioButton">
<RadioButton.Style>
<Style TargetType="RadioButton">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=CheckBoxA, Path=IsChecked}" Value="True"/>
<Condition Binding="{Binding RadioAValue}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="IsChecked" Value="True"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<DataTrigger Binding="{Binding ElementName=CheckBoxA, Path=IsChecked}" Value="False">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
<CheckBox x:Name="CheckBoxA"/>
I have datagrid with some conditional row. And I want if I select particular row in datagrid, The selected color will change based on my record value.
Suppose I have record of Students with IsDropOut Flag.
And then If I click selected record of student, Selected row will change color according to IsDropOut value. If it is true it will set selected row background to red and if IsDropOut is false it will change selected row background to green.
Maybe with like this
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=DataGridCell.IsSelected}" Value="True" />
<Condition Binding="{Binding Path=IsDropOut}" Value="true" />
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="red" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
But that's code is not work. So how to do it? Anyone has suggestion?
Finally I solve this.. Thanks for the idea..
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsDropOut}" Value="True" />
<Condition Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Self}}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="White" />
</MultiDataTrigger>
Try this :
<Style TargetType="DataGridCell">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="IsDropOut" Value="true" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="Red" />
</MultiTrigger>
</Style.Triggers>
</Style>