Create Dynamic DataGrid Column With Style and Trigger in WPF

Introduction

Hi this article demonstrates how to create a DataGridColumn at run time with Styles and Triggers. Normally at design time when we create a DataGrid, we also create the required columns or set the autogenareted column property of the DataGrid to true to create automatically generate the columns based on the bound item source. Suppose you need to create a DataGrid without knowing how many columns you to need to create and you don't know the columns names with their binding value and other properties like cell background color and so on.

In the preceding case this article will help you. This article creates a DatagridColumn at runtime having other properties, like header, cell style, Trigger and so on.

In this article we will learn the following points:

  1. Creating DataGrid Column at runtime and assign to DataGrid.
  2. Binding property name with DataGrid column to display a property value in the DataGrid cell
  3. Adding cell style in the DataGrid at runtime
  4. Adding trigger into DataGrid at runtime
Starting

To create a DataGridColumn at run time you will require the following namespaces. These namespaces help to create controls, binding (required to bind a property with a DataGrid cell), Styles, Triggers and so on.

  1. System.Windows.Controls
  2. System.Windows.Data
  3. System.Windows 

       1. Creating DataGridColumn

       2. Bind property

At design time we are creating DataGridColumns like DataGridTextColumn using XAML like the following code.

  1. <DataGrid x:Name="dgvRates">  
  2. <DataGrid.Columns >  
  3.     <DataGridTextColumn  Binding="{Binding Path=xyz, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header=" XYZ "  MinWidth="110">  
  4.     </DataGridTextColumn>  
  5. </DataGrid>  
Now we will create the same thing using C# code. Use the namespace System.Windows.Controls in your window class if it is not used. Suppose my DataGrid name is "dgvRates" as in the following:
  1. //creates object of datagridtextcolum class  
  2. DataGridTextColumn dataGridTextColumn = new DataGridTextColumn();  
  3.   
  4. // sets header name  
  5. dataGridTextColumn.Header = “XYZ”;  
  6.   
  7. //creates object of binding class , accepts name of property as parameter , whose value to be display  
  8. Binding binding = new Binding(“PropertyName”);  
  9. // sets binding mode  
  10. binding.Mode = BindingMode.TwoWay;   
  11.   
  12. // sets how trigger to be fired.  
  13. binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;   
  14.   
  15. // assigned the object of binding class to object of datagridtextcolumn class;  
  16. dataGridTextColumn.Binding = binding;   
  17.   
  18. // added created column into column list of datagrid (dgvRates);  
  19. dgvRates.Columns.Add(dataGridTextColumn);   

       3. Adding cell style in the DataGrid at runtime

At the design time, to apply a style to the datagrid cell, for example foreground and background colors, we are doing the following XAML code.

  1. <DataGridTextColumn.CellStyle>  
  2.       <Style TargetType="{x:Type DataGridCell}">                             
  3.                 <Setter Property="Background" Value="{Binding Brushes.Black}" />  
  4.                  <Setter Property=" Foreground " Value="{Binding Brushes.White}" />  
  5.       </Style>  
  6.   </DataGridTextColumn.CellStyle>  

 But if we want to set colors with the DataGrid cell at runtime then we are binding the foreground and background properties with a property of datacontext or with a control's background or foreground property like the following XAML code:

  1. <DataGridTextColumn.CellStyle>  
  2. <Style TargetType="{x:Type DataGridCell}">     
  3. <Setter Property="Foreground" Value="{Binding Background, ElementName=txtFont, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>  
  4.     <Setter Property="Background" Value="Binding Background, ElementName=txtBackground, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
  5. </Style>  
  6.   </DataGridTextColumn.CellStyle>  

In the code above the foreground of the DataGrid is set from the background property of the TextBox having the name txtfont and the background is set from the background property of the TextBox txtBackground. The binding mode is two-way because when the background changes both the text box of the cell background and foreground will be changed automatically.

To add the cell style at runtime as in the preceding XAML code, you will need to use the style and setter class that comes under the System.Windows namespace. This class will help you to set the background, font style and Add trigger and so on. A style consists of a list of setters. If you apply this style to an element it sets all properties with the specified values. The idea is quite similar to Cascading Styles Sheets (CSS) that we are familiar with from web development. The following code accomplishes the same thing that is specified in the preceding XAML code.

  1. Style style = new Style(); // creates object of style class  
  2.         style.TargetType = typeof(DataGridCell); sets target type as DataGrid cell  
  3.         Setter setterBackground = new Setter(); // create objects of setter class  
  4.             setterBackground.Property = DataGridCell.BackgroundProperty;  
  5.             setterBackground.Value = Brushes.Green;  
  6.             style.Setters.Add(setterBackground);  
  7.         dataGridTextColumn.CellStyle = style;  

       4. Adding trigger into DataGrid at runtime

We require triggers when we want something to change when something happens in the application. For example we want the background color of a DataGrid cell to change when a value changes that meets a specific criteria. This article has explained how to add a data trigger to a DataGridcell to change the background color.

At design time, to add a data trigger with a DataGrid, we are doing code in XAML like the following code:

  1. DataGridTextColumn.CellStyle>  
  2.                         <Style TargetType="{x:Type DataGridCell}">  
  3.                             <Style.Triggers>  
  4.                                 <DataTrigger Binding="{Binding, UpdateSourceTrigger=PropertyChanged}" Value="<=100">  
  5.                                     <Setter Property="Background" Value="{Binding Brushes.Red, UpdateSourceTrigger=PropertyChanged}" />  
  6.                                 </DataTrigger>  
  7.                                 <DataTrigger Binding="{Binding, UpdateSourceTrigger=PropertyChanged}" Value="<=200">  
  8.                                     <Setter Property="Background" Value="{Binding Brushes.Black, UpdateSourceTrigger=PropertyChanged}" />  
  9.                                 </DataTrigger>  
  10.                                 <DataTrigger Binding="{Binding, UpdateSourceTrigger=PropertyChanged}" Value=">200">  
  11.                                     <Setter Property="Background" Value="Binding Brushes.Green"/>
  12.                                  </DataTrigger>  
  13.                             </Style.Triggers>  
  14.                         </Style>  
  15.                     </DataGridTextColumn.CellStyle>  

In the preceding XAML code if the DataGrid cell value is greater or equal to 100 then the cell background color is read and if <= 200 then Black or > 200 then Green. Now we will do the same thing using C# code. We will need a datatrigger class from the System.Window.Data namespace. See the following C# code that is doing that as XAML.

  1. Style style = new Style();  
  2.                                     style.TargetType = typeof(DataGridCell);  
  3. DataTrigger DT = new DataTrigger();  
  4.   
  5.                                         Binding DataTriggerBinding = new Binding( “bindingName1”);  
  6.                                         DataTriggerBinding.Mode = BindingMode.Default;  
  7.                                         DataTriggerBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;  
  8.                                         DT.Binding = DataTriggerBinding;  
  9.                                         DT.Value = “<=100”;  
  10. Setter DataTriggerSetter = new Setter();  
  11.                                         DataTriggerSetter.Property = DataGridCell.BackgroundProperty;  
  12. DataTriggerSetter.Value = Brushes.Red;  
  13. DT.Setters.Add(DataTriggerSetter);  
  14.                                         style.Triggers.Add(DT);  
  15.   
  16. DataTrigger DT1 = new DataTrigger();  
  17.   
  18.                                         Binding DataTriggerBinding1 = new Binding(“bindingName2”);  
  19.                                         DataTriggerBinding1.Mode = BindingMode.Default;  
  20.                                         DataTriggerBinding1.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;  
  21.                                         DT1.Binding = DataTriggerBinding;  
  22.                                         DT1.Value = “<=200”;  
  23. Setter DataTriggerSetter1 = new Setter();  
  24.                                         DataTriggerSetter1.Property = DataGridCell.BackgroundProperty;  
  25.   DataTriggerSetter1.Value = Brushes.Black;  
  26. DT1.Setters.Add(DataTriggerSetter1);  
  27.                                         style.Triggers.Add(DT1);  
  28.   
  29. DataTrigger DT2 = new DataTrigger();  
  30.   
  31.                                         Binding DataTriggerBinding2 = new Binding(“bindingName3”);  
  32.                                         DataTriggerBinding2.Mode = BindingMode.Default;  
  33.                                         DataTriggerBinding2.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;  
  34.                                         DT2.Binding = DataTriggerBinding2;  
  35.                                         DT2.Value = “<=100”;  
  36. Setter DataTriggerSetter2 = new Setter();  
  37.                                         DataTriggerSetter2.Property = DataGridCell.BackgroundProperty;  
  38. DataTriggerSetter2.Value = Brushes.Red;  
  39. DT2.Setters.Add(DataTriggerSetter2);  
  40.                                         style.Triggers.Add(DT2);  
  41. dataGridTextColumn.CellStyle = style;  
Full Code
  1. //creates object of datagridtextcolum class
    DataGridTextColumn dataGridTextColumn = new DataGridTextColumn();
    // sets header name
    dataGridTextColumn.Header = "Dynamic Column";
    //creates object of binding class , accepts name of property as parameter , whose value to be display
    Binding binding = new Binding("PropertyName");
    // sets binding mode
    binding.Mode = BindingMode.TwoWay;
    // sets how trigger to be fired.
    binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    // assigned the object of binding class to object of datagridtextcolumn class;
    dataGridTextColumn.Binding = binding;
    //code for add style to row
    Style Rowstyle = new Style(); // creates object of style class
    Rowstyle.TargetType = typeof(DataGridRow);//sets target type as DataGrid row
    Setter setterBackground = new Setter(); // create objects of setter class
    setterBackground.Property = DataGridRow.BackgroundProperty;
    setterBackground.Value = Brushes.Black;
    Rowstyle.Setters.Add(setterBackground);
    Setter setterForeGround = new Setter();
    setterForeGround.Property = DataGridRow.ForegroundProperty;
    setterForeGround.Value = Brushes.White;
    Rowstyle.Setters.Add(setterForeGround);
    dgvRate.RowStyle = Rowstyle;
    Style DataGridCellStyle = new Style();
    DataGridCellStyle.TargetType = typeof(DataGridCell);
    DataTrigger DT = new DataTrigger();
    Binding DataTriggerBinding = new Binding("bindingName");
    DataTriggerBinding.Mode = BindingMode.Default;
    DataTriggerBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    DT.Binding = DataTriggerBinding;
    DT.Value = "<=100";
    Setter DataTriggerSetter = new Setter();
    DataTriggerSetter.Property = DataGridCell.BackgroundProperty;
    DataTriggerSetter.Value = Brushes.Red;
    DT.Setters.Add(DataTriggerSetter);
    DataGridCellStyle.Triggers.Add(DT);
    DataTrigger DT1 = new DataTrigger();
    Binding DataTriggerBinding1 = new Binding("bindingName");
    DataTriggerBinding1.Mode = BindingMode.Default;
    DataTriggerBinding1.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    DT1.Binding = DataTriggerBinding;
    DT1.Value = "<=200";
    Setter DataTriggerSetter1 = new Setter();
    DataTriggerSetter1.Property = DataGridCell.BackgroundProperty;
    DataTriggerSetter1.Value = Brushes.Black;
    DT1.Setters.Add(DataTriggerSetter1);
    DataGridCellStyle.Triggers.Add(DT1);
    DataTrigger DT2 = new DataTrigger();
    Binding DataTriggerBinding2 = new Binding("bindingName");
    DataTriggerBinding2.Mode = BindingMode.Default;
    DataTriggerBinding2.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    DT2.Binding = DataTriggerBinding2;
    DT2.Value = ">=200";
    Setter DataTriggerSetter2 = new Setter();
    DataTriggerSetter2.Property = DataGridCell.BackgroundProperty;
    DataTriggerSetter2.Value = Brushes.Red;
    DT2.Setters.Add(DataTriggerSetter2);
    DataGridCellStyle.Triggers.Add(DT2);
    dataGridTextColumn.CellStyle = DataGridCellStyle;
    // added created column into column list of datagrid (dgvRates);
    dgvRate.Columns.Add(dataGridTextColumn);
  2.