How To Get ColumnIndex In XAML to apply style too - wpf

<Style x:Key="myStyle" TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="ColumnIndex" Value="2">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
I remembered I Was able to accomplish this with code similar to this but can't remember how I did it anymore.

If I understand what you are trying to do, you want the text color of the cells in column 2 to be red.
Here is your style...
<Style x:Key="myStyle" TargetType="DataGridCell">
<Setter Property="Foreground" Value="Red"/>
</Style>
Then for the column that you want to style...
<DataGridTextColumn Header="Value" CellStyle="{StaticResource myStyle}"/>

You are targeting "ColumnIndex" which does not exist in DataGridCell class.
Creating column definitions makes adding a style to the second column only much easier to do rather than relying on a trigger.
<DataGrid AutoGenerateColumns="False">
<DataGrid.Resources>
<Style x:Key="myStyle" TargetType="DataGridCell">
<Setter Property="Background" Value="Beige" />
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn />
<DataGridTextColumn CellStyle="{StaticResource myStyle}" />
<DataGridTextColumn />
</DataGrid.Columns>
</DataGrid>

Related

WPF DataGrid AlternatingRowBackground overriding the Style DataTrigger for background

I have a DataGrid where I show many lines of data. To help visually differentiate the rows I've added a background colour to alternating rows.
But, there are some rows that contains very interesting data that I want to attract the user's attention to, and so I use a Style DataTrigger to highlight those specific rows.
My problem is that the alternating background colour takes precedence - only the odd rows (no background colour) show the highlight.
Note, this is a data-bound DataGrid using the MVVM pattern (no "code-behind").
The (very cutdown) code is as follows:
<DataGrid ItemsSource="{Binding FilteredTraceMessages, Mode=OneWay}"
AlternatingRowBackground="AliceBlue"
.......>
<DataGrid.Columns>
....
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Severity}" Value="Error">
<Setter Property="Background" Value="LightSalmon"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Severity}" Value="Warning">
<Setter Property="Background" Value="LemonChiffon"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
</DataGrid>
You have to set the Backround on the same precedence level. See Dependency Property Setting Precedence List
Delete AlternatingRowBackground="AliceBlue" from the DataGrid and put AlternationCount="2" there. Then add at the first place a trigger for AlternationIndex.
<DataGrid ItemsSource="{Binding FilteredTraceMessages, Mode=OneWay}" AlternationCount="2"
.......>
<DataGrid.Columns>
....
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="AlternationIndex" Value="1">
<Setter Property="Background" Value="AliceBlue"/>
</Trigger>
<DataTrigger Binding="{Binding Severity}" Value="Error">
<Setter Property="Background" Value="LightSalmon"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Severity}" Value="Warning">
<Setter Property="Background" Value="LemonChiffon"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
</DataGrid>

Hide DataGrid borders (or what left of it)

I don't really know how to describe it. Best thing is to show it:
Do you see those thin black lines?
Here is Xaml snippet:
<DataGrid Grid.Row="4" Grid.Column="1" ItemsSource="{Binding RunnedTests}" Margin="5"
HeadersVisibility="None" AutoGenerateColumns="False" IsEnabled="False"
GridLinesVisibility="None" RowBackground="#FF268AEC" BorderBrush="#FF268AEC" BorderThickness="0">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Width="4*" />
<DataGridTextColumn Binding="{Binding PassedOrFailed}" Width="*">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Foreground" Value="Red" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsPassed}" Value="True">
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
The BorderBrush & BorderThickness doesn't really do anything for it. Without those properties it will stay the same.
Here is a Picture of the same DataGrid without the RowBackground property:
More notes:
Background property of DataGrid does nothing
I don't know if you can see from my code, but hides there a frustrating struggle with DataTrigger. I wanted to display the words "passed" or "failed" depending on the IsPassed bool property via DataTrigger, but could not make it. At the end I had to compromise and create the property PassedOrFailed in the model. It is quite stupid in my point of view, can you suggest a way to accomplish it?
Thanks!
Update:
I forgot to mention two additional styles:
<Style TargetType="DataGridCell">
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="15" />
<Setter Property="Margin" Value="5" />
</Style>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="Transparent" />
</Style>

Spellchecker on DataGridTextColumn

Good day. I'm still a junior programmer and recently started coding in WPF. I have a datagrid where I generate my own columns. In one specific column, a DataGridTextColumn, I have to apply a spell check (the user can add comments to this field). But I can't manage to do this. I have tried applying a style but no luck. Any assistance would be appreciated! Here is the coding for the column:
<DataGridTextColumn x:Name="clValueComment" Binding="{Binding CommentColumn, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="ROOTCAUSE OR COMMENT" Width="*" IsReadOnly="False" Style="{StaticResource Spell}">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black" />
</Trigger>
<DataTrigger Binding="{Binding valueTypeID}" Value="1">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Label IsEnabled="False"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
After playing around with some more of the Styling options, I found a solution that seems to be working. I'll post it as an answer for someone who might come across the same requirement. The XAML coding that did the trick is:
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="TextBox">
<Setter Property="SpellCheck.IsEnabled" Value="True"/>
</Style>
</DataGridTextColumn.EditingElementStyle>

Template for WPF DataGridTextColumn ElementStyle and EditElementStyle with Binding

I have a WPF DataGrid that has 10 DataGridTextColumns displaying numeric data that require identical formatting. I want the EditingElementStyle number formatting (raw decimal or float) to be different than the ElementStyle formatting (formatted percent or money). If it matters, the DataContext of my grid is a CollectionViewSource.
I'd like to come up with a reusabe Style or Template resource to define my columns if possible. The XAML for my 10 DataGridTextColumns is nearly identical. I can't quite figure out how to use TemplateBinding, Element binding or RelativeSource binding in my template to ensure that each column gets the correct binding once templates are resolved.
My ultimate goal is to be able to define my DataGridTextColumns as follows:
<DataGridTextColumn x:Name="dingCutoffPctColumn"
Binding="{Binding CutoffPct}" Header="Cutoff %" Width="60"
ElementStyle="{StaticResource NumberElementStyle}"
EditingElementStyle="{StaticResource EditErrorStyle}" />
Here's a representation of the working XAML that I'm currently using:
<DataGrid x:Name="myDataGrid" AutoGenerateColumns="False"
Margin="10,67,13,0" Height="200" EnableRowVirtualization="True"
ItemsSource="{Binding}" VerticalAlignment="Top">
<DataGrid.Resources>
<Style x:Key="EditErrorStyle" TargetType="{x:Type TextBox}">
<Setter Property="Padding" Value="-2"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="NumberElementStyle" TargetType="{x:Type TextBlock}">
<Setter Property="TextAlignment" Value="Right"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="id" Binding="{Binding ID}"
Visibility="Collapsed" />
<DataGridTextColumn x:Name="name" Header="Name"
Binding="{Binding Name,
TargetNullValue=<enter new name>}" />
<DataGridTextColumn x:Name="cutoffPct" {Binding CutoffPct}"
Header="Cutoff %" Width="60">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}"
BasedOn="{StaticResource NumberElementStyle}">
<Setter Property="Text"
Value="{Binding CutoffPct, StringFormat=P}"/>
</Style>
</DataGridTextColumn.ElementStyle>
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="{x:Type TextBox}"
BasedOn="{StaticResource EditErrorStyle}">
<Setter Property="Text"
Value="{Binding CutoffPct,
ValidatesOnExceptions=True, StringFormat=\{0\}}"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
Thanks for your help

setting text on DataGridTextColumn

I am using a DataTrigger to replace empty cells with '-' text. My code:
<DataGridTextColumn Header="Time taken" Binding="{Binding Path=finish}" Width="Auto" x:Name="x">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=finish}" Value="{x:Null}">
<Setter Property="TextBlock.Text" Value="-" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
But I couldn't find the text being set. I tried changing the background of the TextBlock and its working. Why cant I set the Text property?
The Binding in the column might be overriding the Setter.
But you don't need a data trigger to do this. As there is a property in the binding that you can set for these kinds of scenarios.
TargetNullValue allows you to set a value in the case that the bindings path is null.
Binding="{Binding Path=finish, TargetNullValue=Whatever you want}"
Taken From:
What's the simplest way to display NULL values as "NULL" with WPF Data Binding?
Namespace
xmlns:sys="clr-namespace:System;assembly=mscorlib"
<DataGridTextColumn Header="Time taken" Binding="{Binding Path=finish}" Width="Auto" x:Name="x">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Text" Value="{Binding Path=finish}"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=finish}" Value="{x:Static sys:String.Empty}">
<Setter Property="Text" Value="-"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

Resources