I'm writing a WPF application which makes use of the DataGrid control. I'm using the MaterialDesign theme to style the application and this gives a nice look and feel.
However for complex reasons I wont go into here I'm required to add the columns into the dataGrid programmatically. For some of the columns I'm also styling the columns to highlight pass / fail in red. When I do this I loose 'some of the styling' provided by material design for that columns. Namely the Horizontal and Vertical alignment.
The code to the above is as follows:
// Define Setter
Setter setterResultFail = new Setter();
setterResultFail.Property = DataGridCell.BackgroundProperty;
setterResultFail.Value = Brushes.Red;
// Create a column for the Site.
var currentColumn = new DataGridTextColumn();
currentColumn.Header = "Device #";
currentColumn.Binding = new Binding("Device");
ResultsDataGrid.Columns.Add(currentColumn);
// Create a column for the Site.
currentColumn = new DataGridTextColumn();
currentColumn.Header = "Site";
currentColumn.Binding = new Binding("Site");
ResultsDataGrid.Columns.Add(currentColumn);
// Create a column for the Pass Fail.
currentColumn = new DataGridTextColumn();
currentColumn.Header = "Pass Fail";
currentColumn.Binding = new Binding("PassFail") { Converter = new BooleanToPassFailConverter() };
// Create cellstyle to make the cell 'red' when the PassFail value is False. ( this is done via a data trigger )
cellStyle = new Style(typeof(DataGridCell));
// Define First DataTrigger that sets a CELL red if the value is a fail.
dataTrigger = new DataTrigger();
dataTrigger.Value = "False";
dataTrigger.Binding = new Binding("PassFail");
dataTrigger.Setters.Add(setterResultFail);
// Add the data-triggers to the cell style.
cellStyle.Triggers.Clear();
cellStyle.Triggers.Add(dataTrigger);
// Apply the newly created cell style.
currentColumn.CellStyle = cellStyle;
ResultsDataGrid.Columns.Add(currentColumn);
Clearly the new cellStyle is used instead of the MaterialDesign style. I've tried setting the values for vertical / horizontal manually but I can't get it to look correct:
Setter setterTextContentHorizonalAlignment = new Setter();
setterTextContentHorizonalAlignment.Property = DataGridCell.HorizontalContentAlignmentProperty;
setterTextContentHorizonalAlignment.Value = HorizontalAlignment.Center;
Setter setterTextContentVerticalAlignment = new Setter();
setterTextContentVerticalAlignment.Property = DataGridCell.VerticalContentAlignmentProperty;
setterTextContentVerticalAlignment.Value = VerticalAlignment.Center;
Setter setterTextHorizontalAlignment = new Setter();
setterTextHorizontalAlignment.Property = DataGridCell.HorizontalAlignmentProperty;
setterTextHorizontalAlignment.Value = HorizontalAlignment.Center;
Setter setterTextVerticalAlignment = new Setter();
setterTextVerticalAlignment.Property = DataGridCell.VerticalAlignmentProperty;
setterTextVerticalAlignment.Value = VerticalAlignment.Center;
cellStyle.Setters.Add(setterTextContentHorizonalAlignment);
cellStyle.Setters.Add(setterTextContentVerticalAlignment);
cellStyle.Setters.Add(setterTextHorizontalAlignment);
cellStyle.Setters.Add(setterTextVerticalAlignment);
Is there a way I can add to the style rather than replace it...similar to the BasedOn approch in XAML?
After much wasting of time on this question I came across Danny Beckett's similar question and King King's answer. By using his answer and applying it to the specific cell I was having trouble with it fixed the issue:King King's answer
// Create a column for the Pass Fail.
currentColumn = new DataGridTextColumn();
currentColumn.Header = "Pass Fail";
currentColumn.Binding = new Binding("PassFail") { Converter = new BooleanToPassFailConverter() };
// Create cellstyle to make the cell 'red' when the PassFail value is False. ( this is done via a data trigger )
cellStyle = new Style(typeof(DataGridCell));
// Define First DataTrigger that sets a CELL red if the value is a fail.
dataTrigger = new DataTrigger();
dataTrigger.Value = "False";
dataTrigger.Binding = new Binding("PassFail");
dataTrigger.Setters.Add(setterResultFail);
// Add the data-triggers to the cell style.
cellStyle.Triggers.Clear();
cellStyle.Triggers.Add(dataTrigger);
//root visual of the ControlTemplate for DataGridCell is a Border
var border = new FrameworkElementFactory(typeof(Border));
border.SetBinding(Border.BorderBrushProperty, new Binding("BorderBrush")
{
RelativeSource = RelativeSource.TemplatedParent
});
border.SetBinding(Border.BackgroundProperty, new Binding("Background") { RelativeSource = RelativeSource.TemplatedParent });
border.SetBinding(Border.BorderThicknessProperty, new Binding("BorderThickness") { RelativeSource = RelativeSource.TemplatedParent });
border.SetValue(SnapsToDevicePixelsProperty, true);
//the only child visual of the border is the ContentPresenter
var contentPresenter = new FrameworkElementFactory(typeof(ContentPresenter));
contentPresenter.SetBinding(SnapsToDevicePixelsProperty, new Binding("SnapsToDevicePixelsProperty") { RelativeSource = RelativeSource.TemplatedParent });
contentPresenter.SetBinding(VerticalAlignmentProperty, new Binding("VerticalContentAlignment") { RelativeSource = RelativeSource.TemplatedParent });
contentPresenter.SetBinding(HorizontalAlignmentProperty, new Binding("HorizontalContentAlignment") { RelativeSource = RelativeSource.TemplatedParent });
//add the child visual to the root visual
border.AppendChild(contentPresenter);
//here is the instance of ControlTemplate for DataGridCell
var template = new ControlTemplate(typeof(DataGridCell));
template.VisualTree = border;
//define the style
cellStyle.Setters.Add(new Setter(TemplateProperty, template));
cellStyle.Setters.Add(new Setter(VerticalContentAlignmentProperty, VerticalAlignment.Center));
cellStyle.Setters.Add(new Setter(HorizontalContentAlignmentProperty, HorizontalAlignment.Center));
// Apply the newly created cell style.
currentColumn.CellStyle = cellStyle;