Search code examples
c#wpfwpfdatagrid

how to change datagrid row background color with value taken from database in wpf


I want to change datagrid row background color, by taking value from Database. I have 2 value "ERROR" and "OK". If Column string value is ERROR then row color will be red and if OK then It must be Green. This value get from database by executing query. I have these values in dataset. I am not clear that how to achieve this?

I have tried below code:

<Window x:Class="stackDatagridColor.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModels="clr-namespace:stackDatagridColor"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <viewModels:viewmodel x:Key="viewmodel"/>
    <viewModels:BrushConverter x:Key="BrushConverter"/>
</Window.Resources>
<Grid>
    <StackPanel>
        <DataGrid ItemsSource="{Binding Collection, Mode=TwoWay, Source={StaticResource viewmodel}, UpdateSourceTrigger=PropertyChanged}">
            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Status}" Value="ERROR">
                            <Setter Property="Background" Value="Red"></Setter>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Status}" Value="OK">
                            <Setter Property="Background" Value="Green"></Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.RowStyle>
        </DataGrid>
    </StackPanel>
</Grid>

ViewModel:

public class viewmodel : INotifyPropertyChanged
{

    private ObservableCollection<myItem> collection;
    public ObservableCollection<myItem> Collection
    {
        get { return collection; }
        set { collection = value; OnPropertyChanged("Collection"); }
    }


    public viewmodel()
    {
        Collection = new ObservableCollection<myItem>();
        myItem item1 = new myItem { Name = "name1", Status = "OK" };
        myItem item2 = new myItem { Name = "name2", Status = "ERROR" };
        DispatchService.Invoke(() =>
            {
                Collection.Add(item1);
            Collection.Add(item2);
            });
    }


    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #endregion
}

Simple Class

public class myItem
{
    public string Status { get; set; }
    public string Name { get; set; }
}

Dispatcher class

public static class DispatchService
{
    public static void Invoke(Action action)
    {
        Dispatcher dispatchObject = Application.Current.Dispatcher;
        if (dispatchObject == null || dispatchObject.CheckAccess())
        {
            action();
        }
        else
        {
            dispatchObject.Invoke(action);
        }
    }
}

Converter:

public class BrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string input = value as string;
        switch (input)
        {
            case "ERROR":
                return Brushes.Red;
            case "OK":
                return Brushes.Green;
            default:
                return DependencyProperty.UnsetValue;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

I just want to bind dataset column to trigger. If trigger get ERROR string then background row color change to red and vice versa.


Solution

  • Firstly Collection property should be declared in this way:

    public DataSet Collection { ... }
    

    ItemSource binding in XAML should be also changed:

    ItemsSource="{Binding Path=Collection.Tables[Table1], Mode=OneWay,...
    

    In the code above Table1 is a name of a table within a dataset you want to bind to. To test this code create a simple dataset in this way:

     public viewmodel()
     {
            var tb = new DataTable("Table1");
            tb.Columns.Add("Status");
            tb.Columns.Add("Name");
    
            tb.Rows.Add("OK", "name1");
            tb.Rows.Add("ERROR", "name2");
            tb.Rows.Add("ERROR", "name3");
    
            Collection2 = new DataSet();
            Collection2.Tables.Add(tb);
     }