Reputation: 3061
I have a DataGrid with an AlternatingRowBackground (white and blue). Certain options, however, can make some rows readonly (the second half of rows, for instance), in which case the background is changed to LightGrey. The DataGrid is populated dynamically, so all of these background changes were done in code-behind.
In case the DataGrid must have the first half of its rows editable and the second half readonly, for instance, the code is
if (Symmetric.IsChecked == true)
{
int n = (nPoints % 2 == 0 ? nPoints / 2 : (nPoints + 1) / 2);
for (int i = 1; i < n; i++)
{
//resultSections is the DataContext of the (DataGrid)SectionsGrid
resultSections[i].IsReadOnly = false;
var r = SectionsGrid.GetRow(i);
if (r == null)
continue;
r.Background = (i % 2 == 0 ? Brushes.White : Brushes.AliceBlue);
}
for (int i = n; i < nPoints; i++)
{
resultSections[i].X = ProjectProperties.I.BeamLength - resultSections[nPoints - i - 1].X;
resultSections[i].IsReadOnly = true;
var r = SectionsGrid.GetRow(i);
if (r == null)
continue;
r.Background = Brushes.LightGray;
}
}
This code works fine so long as all the rows are within view. Should there be rows that can only be seen by scrolling, then SectionsGrid.GetRow(i)
returns null and the background is not altered. Is there a way of setting the background of a row without it being painted?
I don't know how I would do this in .xaml with DataTriggers which I know are usually used to define changing backgrounds. The problem is that the background depends on whether either of two CheckBoxes is checked (only one can be checked), with the behavior being different depending on the CheckBox. Also, if one of the CheckBoxes is checked and then unchecked, the background needs to revert back to the AlternatingRowBackground, which in turn depends on the row number.
EDIT:
I realized that setting a DataTrigger to the row's DataContext's .IsReadOnly
property might work, so I created the following:
<Style x:Key="ReadOnlyCheck" TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsReadOnly}" Value="True">
<Setter Property="Tag" Value="ReadOnly" />
<Setter Property="Background" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
This works in that setting .IsReadOnly
turns the background LightGray, but it still fails on rows that are out of "scroll-range". Once I scroll, they haven't gone gray.
Upvotes: 0
Views: 1164
Reputation: 81253
Virtualization is On by default for dataGrid that means dataGridRow gets generated for only visible rows. Other rows gets generated only once they come in viewport after scrolling.
In case you want to get all rows at a time, you can turn off the virtualization on dataGrid by setting VirtualizingStackPanel.IsVirtualizing="False"
.
<DataGrid VirtualizingStackPanel.IsVirtualizing="False"/>
Also, in case you don't want to turn off Virtualization, hook Loaded event of DataGridRow which gets fired whenever row gets generated and set background in the handler.
<DataGrid>
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<EventSetter Event="Loaded" Handler="Row_Loaded"/>
</Style>
</DataGrid.ItemContainerStyle>
</DataGrid>
Code behind:
private void Row_Loaded(object sender, RoutedEventArgs e)
{
(sender as DataGridRow).Background = Brushes.AliceBlue;
}
Upvotes: 1