setting text on DataGridTextColumn - wpf

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>

Related

Why is the DataTrigger to set the header of a DataGridColunm not working?

I am trying to set the header of the DataGrid columns according to a value of a property in my view model. I am using this code:
<DataGridTextColumn.Header>
<TextBlock>
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Text" Value="My Default Header"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ucPrincipal, Path=DataContext.MyPrperty.ID}" Value="3" >
<Setter Property="Text" Value="Header 2"/>
</DataTrigger>
<DataTrigger Binding="{Binding DataContext.MyProperty.ID, RelativeSource={RelativeSource AncestorType={x:Type local:myUcViewType}}}" Value="4" >
<Setter Property="Text" Value="Header 3"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataGridTextColumn.Header>
But the header is always set to the default value. The values of ID are set to 3 and 4 correctly.
I am trying to use two different ways to get the value of the ID which is the source property that is used by the DataTrigger to set the header text.
Thanks.

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>

How To Get ColumnIndex In XAML to apply style too

<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>

Setter in DataTemplate Target parent Element (Influence DataGridRow from CellTemplate)

i need to collapse the current DataGridRow based on a cell's DataContext value ,
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentControl Content="{Binding}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsParentExpanded}" Value="False">
<!-- Here i wan't to Collapse the DataGridRow-->
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
any ideas how this can be done ?
just to clarify i wan't there to be a Setter where the Target in the RelativeSource of type DataGridRow.
currently i apply this change threw :
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsParentExpanded}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
i was wondering if there's a different way , only using xaml of course , since i can traverse up the visual tree and do that in code.
You should do this in RowStyle like below
<DataGrid>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding IsParentExpanded}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
</DataGrid>

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

Resources