Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Dynamically Change a Row's Style Based On Row Data?

Tags:

c#

wpf

datagrid

How does one style a specific row or rows in a WPF Datagrid during runtime? Each change depends on some values of the shown data?

like image 839
Seffix Avatar asked Nov 29 '22 16:11

Seffix


1 Answers

I can't tell from your question whether you are adding columns to your grid at run time, but either way you can add a CellStyle to the grid at design time that handles your specific styling needs using DataTriggers.

For instance, the following would make all rows red where the Name property = "Billy Bob":

    <DataGrid AutoGenerateColumns="True" Name="dataGrid1">
        <DataGrid.CellStyle>
            <Style TargetType="{x:Type DataGridCell}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Name}" Value="Billy Bob" >
                        <Setter Property="Background" Value="Red" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.CellStyle>
    </DataGrid>

If you are adding columns programmatically at run time and you want to apply a certain style to them, you can still define those styles at design time in your xaml.

    <DataGrid AutoGenerateColumns="False" Name="dataGrid1">
        <DataGrid.Resources>
            <Style TargetType="{x:Type DataGridCell}" x:Key="MyCellStyle">
                <Setter Property="Foreground" Value="Green"/>
            </Style>
        </DataGrid.Resources>
        ...

Then when you are adding the columns you can apply that style to them:

col.CellStyle = (Style)dataGrid1.Resources("MyCellStyle");

Update

If you have a list of songs and you want to change the row color of every song that has an artist whose name starts with an "a", then you could use an IValueConverter.

The following converter would do the trick:

public class ArtistNameConverter : IValueConverter
{
    public object Convert(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        try
        {
            return value.ToString().StartsWith(parameter.ToString());
        }
        catch
        {
            return false;
        }
    }

    public object ConvertBack(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Then you could use the converter in your xaml like so:

    <DataGrid AutoGenerateColumns="True" Name="dataGrid1">
        <DataGrid.Resources>
            <converters:ArtistNameConverter x:Key="ArtistNameConverter"></converters:ArtistNameConverter>
        </DataGrid.Resources>
        <DataGrid.CellStyle>
            <Style TargetType="{x:Type DataGridCell}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ArtistName, Converter={StaticResource ArtistNameConverter}, ConverterParameter=a}" Value="True" >
                        <Setter Property="Background" Value="Red" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.CellStyle>
    </DataGrid>

Notice how I am passing an "a" into the converter as the parameter. You can pass in whatever letter you want, and the rows that have artists that start with that letter will have their background color set to red.

Update 2

If you want to pass in a variable of some sort to the converter, you can use MultiBinding.

The Converter would look like this:

public class ArtistNameConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, 
        System.Globalization.CultureInfo culture)
    {
        try
        {
            return values[0].ToString().StartsWith(values[1].ToString());
        }
        catch
        {
            return false;
        }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, 
        System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

The first parameter passed in is the artist name, the second is the letter.

And you would use it in your grid like this:

        <DataGrid.CellStyle>
            <Style TargetType="{x:Type DataGridCell}">
                <Style.Triggers>
                    <DataTrigger Value="True" >
                        <DataTrigger.Binding>
                            <MultiBinding Converter="{StaticResource ArtistNameConverter}">
                                <Binding Path="ArtistName" />
                                <Binding Mode="OneWay" ElementName="FirstLetter" Path="Text" />
                            </MultiBinding>
                        </DataTrigger.Binding>
                        <Setter Property="Background" Value="Red" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.CellStyle>

In this example, the first letter is coming from the "Text" property of a control called "FirstLetter". You can change that binding to whatever you want.

like image 115
kevev22 Avatar answered Dec 10 '22 14:12

kevev22