Reputation: 191
I have a strange rendering issue with my wpf DataGrid on Win7 when the the display is set to Medium - 125%.The expected black vertical border line between the 2nd and 3rd column is not visible.
<DataGrid ItemsSource="{Binding Rows}" AutoGenerateColumns="False">
<DataGrid.Resources>
<Style TargetType="DataGridCell" >
<Setter Property="Background" Value="Orange"></Setter>
<Setter Property="BorderThickness" Value="0"></Setter>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn></DataGridTextColumn>
<DataGridTextColumn Width="150" ></DataGridTextColumn>
<DataGridTextColumn></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
This is the simplest code i can reproduce the problem with. You can use any viewmodel to see this problem. Changing the Width from 150 to 150.1 for example fixes the problem. Can you guys explain to me what happens? How can I avoid this to happen?
Upvotes: 4
Views: 1444
Reputation: 1990
The problem is in discrepancy in how DataGrid
calculates position and size of each column. Simple example: when you set Width
of DataGridColumn
to 95.0 the actual rendered with of column is 95.2; however, DataGrid
will use 95.0 to calculate column X position, but not 95.2.
This discrepancy manifests itself in missing borders on some columns, as the next column "eats" by one pixel into space of the previous column due to missing fractional part.
The solution is to set correct Width
for DataGridColumn
, so it will be exactly the same as the rendered width. In this case DataGrid
becomes aware of fractional part and all borders will be in place.
You can use the code below to calculate the width of column in "DPI aware" fashion before it is rendered. I don't claim credits for the code, as I got it from here https://habrahabr.ru/post/216833/.
var dpiProperty = typeof(SystemParameters).GetProperty("Dpi", BindingFlags.NonPublic | BindingFlags.Static);
var dpi = (int)dpiProperty.GetValue(null, null);
var pixelSize = 96.0 / dpi;
foreach (var dataGridColumn in this.DataGrid.Columns)
{
var actualColumnWidth = dataGridColumn.Width.DisplayValue + (pixelSize / 2);
var div = (actualColumnWidth * 1000) / (pixelSize * 1000);
actualColumnWidth = (int)div * pixelSize;
dataGridColumn.Width = new DataGridLength(actualColumnWidth, DataGridLengthUnitType.Pixel);
}
Upvotes: 2