更改不可见的DataGrid行的背景色

本文关键字:DataGrid 背景色 | 更新日期: 2023-09-27 18:25:01

我有一个带有AlternatingRowBackground(白色和蓝色)的DataGrid。但是,某些选项可以使某些行只读(例如,后半行),在这种情况下,背景将更改为LightGrey。DataGrid是动态填充的,因此所有这些后台更改都是在代码隐藏中完成的。

例如,如果DataGrid的前半行必须可编辑,后半行必须只读,则代码为

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;
    }
}

只要所有行都在视图中,此代码就可以正常工作。如果存在只能通过滚动才能看到的行,则SectionsGrid.GetRow(i)将返回null,并且不会更改背景。有没有一种方法可以在不绘制的情况下设置一行的背景?

我不知道在.xaml中如何使用DataTriggers来实现这一点,我知道这些触发器通常用于定义不断变化的背景。问题是,背景取决于是否选中两个复选框中的任何一个(只能选中一个),而行为则因的复选框而不同。此外,如果先选中复选框中的一个复选框,然后再取消选中,则背景需要恢复为AlternatingRowBackground,这又取决于行号。

编辑:

我意识到将DataTrigger设置为行的DataContext的.IsReadOnly属性可能会起作用,所以我创建了以下内容:

<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>

这是因为设置.IsReadOnly将背景变为浅灰色,但在超出"滚动范围"的行上仍然失败。一旦我滚动,它们就没有变灰。

更改不可见的DataGrid行的背景色

dataGrid 默认情况下,虚拟化处于启用状态,这意味着只为可见行生成dataGridRow。其他行只有在滚动后进入视口时才会生成。

如果您想一次获取所有行,可以通过设置VirtualizingStackPanel.IsVirtualizing="False"来关闭dataGrid上的虚拟化。

<DataGrid VirtualizingStackPanel.IsVirtualizing="False"/>

此外,如果您不想关闭虚拟化,hook DataGridRow的Loaded事件,每当生成行并在处理程序中设置背景时就会触发该事件。

<DataGrid>
    <DataGrid.ItemContainerStyle>
        <Style TargetType="DataGridRow">
            <EventSetter Event="Loaded" Handler="Row_Loaded"/>
        </Style>
    </DataGrid.ItemContainerStyle>
</DataGrid>

代码隐藏:

private void Row_Loaded(object sender, RoutedEventArgs e)
{
    (sender as DataGridRow).Background = Brushes.AliceBlue;
}