I am working on a c# WPF project which I am using a style trigger to style the background colour of the each row based on one of the cell values.
Below is my style trigger.
<Window.Resources>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Highest Alarm Level}" Value="Critical">
<Setter Property="Background" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding Highest Alarm Level}" Value="Medium">
<Setter Property="Background" Value="Orange" />
</DataTrigger>
<DataTrigger Binding="{Binding Highest Alarm Level}" Value="Warning">
<Setter Property="Background" Value="Yellow" />
</DataTrigger>
<DataTrigger Binding="{Binding Highest Alarm Level}" Value="Info">
<Setter Property="Background" Value="White" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
What I need to be able to do, is under certain circumstances I don't want this style to be used, so what I am after, is if in the C# code a certain condition becomes to true, I want to disable all of the styling done above to not be used, i.e. all of the styling is turned off so the background colour of the rows are not set.
Add a Key to your custom DataGridRow Style
<Style TargetType="DataGridRow" x:Key="MyRowStyle">
<!-- Define Triggers -->
</Style>
Then you just need to switch between default and custom styles.
If you set Style with null, that means the default Style will be applied
dataGrid.RowStyle = _boolCondition ? this.FindResource("MyRowStyle") as Style : null;
Related
I have a datagrid "Funds" bind to a listcollectionview.
I want to highlight specific rows in datagrid based on few rules. The fundGroupsList is the list of group names. The rule1 is to find the misalignment within members of a group.
One of the ways to do that is to create a boolean property (ex. IsRule1Failed) in Entries and save the fail result foreach row.
Then, in XAML use DataTriggers to change the background color.
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="BurlyWood" />
</Trigger>
<DataTrigger Binding="{Binding DataContext.IsRule1Failed}" Value="True">
<Setter Property="Background" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
You can also simply change the CSS Class of the row.
GridView.SelectedRowStyle.CssClass = "selectedrow";
I need to flip between two views dynamically based on a boolean flag in my ViewModel.
I thought it would be as simple as:
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="Content" Value="{StaticResource View1}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsShowingView2}">
<Setter Property="Content" Value="{StaticResource View2}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
However, View2 never gets displayed, even if IsShowingView2 is always true.
Any ideas anyone? All the examples I can find seem to be altering the ContentTemplate instead, but I have no need to do that. I just want different content.
You're not actually setting a value for the DataTrigger
<DataTrigger Binding="{Binding IsShowingView2}" Value="True">
<Setter Property="Content" Value="{StaticResource View2}" />
</DataTrigger>
Also check for binding errors in the output window.
after having found much help on stackoverflow, I am now struggling with a problem I could not find an answer for yet. My goal is the following:
I have a datagrid in a wpf/c# application filled with figures. Dependending on whether the figure is positive or negative, I want to change the foreground font to green or red. The itemsource for the datagrid is a list of my own class which includes the following elements:
string description
a list of 12 doubles called totalMoney
I have manually configured the columns for the datagrid so that the first shows the description, then the value of totalMoney[0], then totalMoney[1] and so on. After some searching, I found a way to change the foreground colour of the individual cells based on the values here on stackoverflow via a datatrigger method plus IValueConverter with the following code:
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding totalMoney[2], Converter={StaticResource money}}" Value="1">
<Setter Property="Foreground" Value="Green"/>
</DataTrigger>
<DataTrigger Binding="{Binding totalMoney[2], Converter={StaticResource money}}" Value="0">
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
<DataTrigger Binding="{Binding totalMoney[2], Converter={StaticResource money}}" Value="-1">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
However, as you see in the code, in WPF I have to reference the Binding to an individual item in my List (totalMoney[X]). I therefore have to manually set the style for each Column in my datagrid. As I want to use the style in several datagrids, this seems to me as highly unpractical.
My question is therefore - is it possible to define the style so that it changes depending on the value of a cell in general? Or is there maybe a completely different way to achieve my goal that I have overlooked?
Thank you for your help.
At first glance, you could use the following style for all totalMoney[] columns ...
<Style TargetType="{x:Type TextBlock}" x:Key="MoneyIndicatorStyle">
<Style.Triggers>
<DataTrigger
Binding="{Binding Text, RelativeSource={RelativeSource Self},
Converter={StaticResource money}}"
Value="1">
<Setter Property="Foreground" Value="Green"/>
</DataTrigger>
<DataTrigger
Binding="{Binding Text, RelativeSource={RelativeSource Self},
Converter={StaticResource money}}"
Value="0">
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
<DataTrigger
Binding="{Binding Text, RelativeSource={RelativeSource Self},
Converter={StaticResource money}}"
Value="-1">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
But here is a potential catch... if tommorrow you decide that the text of these textblocks is going to be a formatted currency like this... $(1,00) i.e. negative 100 dollars in accounting world, then the converter could have to cast this formatted string into a locale-neutral number i.e -100.00 and yield 0, 1 or -1 based on the current logic in converter.
Right now your converter is at ease because it receives a straightforward numeric value (totlaMoney[n]) from your model but using the above style it will rely on the Text displayed by the Textblock!
So the decision is yours.
I'm using the WPF DataGrid and have it set to place a red border around any row that the user modifies. It works well, however when the border appears all the cells inside that row get pushed over a pixel or two. In other words a cell's left and right border no longer lines up with the one above or below it, so it looks weird.
Here's the code I'm using to get the red border to appear OnEdit (Note: IsDirty is a property on my bound object that's set when a value gets modified):
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDirty}" Value="true">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="1" />
</DataTrigger>
</Style.Triggers>
</Style>
What can I add so that I can modify the red border margins so that it won't interfere with the cells' borders?
Thanks
One way could be to apply border to each row rather than the dirty one but set the border to transparent and set the border to red for the row which is actually dirty
Something like
<Style TargetType="DataGridRow">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="1" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsDirty}" Value="true">
<Setter Property="BorderBrush" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
The Visual Tree looks something like this
DataGridRow
Border
DataGridCellsPresenter
When you change the BorderThickness of the Border you could compensate this by adding negative Margin.Left to the DataGridCellsPresenter at the same time. Not the prettiest solution but it works
<DataGrid ...>
<DataGrid.Resources>
<Style TargetType="DataGridCellsPresenter">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDirty}" Value="true">
<Setter Property="Margin" Value="-1,0,0,0" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDirty}" Value="true">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="1" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<!--...-->
</DataGrid>
<Style x:Key="originalStyle" TargetType="TextBox">
...setters...
<Style.Triggers>
<DataTrigger Binding="{Binding yyy}" Value="1">
<Setter Property="FontSize" Value="{DynamicResource xxx}"/>
</DataTrigger>
</Style.Triggers>
</Style>
I like everything in the Style except for the DataTrigger which I want to remove. How can change it?
<Style x:Key="derivedStyle" BasedOn="{StaticResource originalStyle}">
...How to remove the DataTrigger???....
</Style>
You could make a "base style" containing all the common stuff, and create two styles BasedOn that style.