WPF datagrid -如何根据值设置单元格背景颜色

g0czyy6m  于 2022-11-18  发布在  其他
关注(0)|答案(2)|浏览(364)

我想根据其值设置datagrid单元格背景色
我的理解是,通常我需要创建一个类Then { get:set:} data属性,将数据集合绑定到datagrid itemsource,最后使用datatrigger设置背景颜色
但是,在我的场景中,数据是动态的,而不是来自列4的静态数据(在下面的示例屏幕截图中,从列“Data 001”开始)
也就是说
1.列数是动态的;
1.列标题名称是动态的;

所以我没有创建数据类,而是先把数据放到字典里
然后从字典转换为数据表,再将数据表转换为数据视图,最后绑定到ItemsSource。
大致如下:

//viewModel
var dtCalcResult = new DataTable();
DtView = dtCalcResult.AsDataView();
 
//xaml
<DataGrid 
            x:Name="dtgdTest" 
            HorizontalAlignment="Stretch" 
            VerticalAlignment="Stretch"
            Margin="10" 
            ItemsSource="{Binding DtView}"
            RowHeight="16"
            FrozenColumnCount="3"
            ColumnHeaderHeight="24"
            EnableRowVirtualization="True"
            EnableColumnVirtualization="True"
            Loaded="dtgdTest_Load"
            >

现在我的问题是如何分配单元格的背景颜色由其值?
我尝试过以下工作方式-〉
使用GetCellContent()获取单元格值,然后根据值设置背景颜色
大概是这样的:

// GET ROW COUNT
                var rowCount = targetDataGrid.Items.Count;
                for (int i = 0; i < rowCount; ++i)
                {
                    // GET ROW OBJECT
                    var row = targetDataGrid.ItemContainerGenerator.ContainerFromIndex(i) as DataGridRow;

                    if (row == null)
                    {
                        // USE ScrollIntoView() TO THAT ROW
                        targetDataGrid.UpdateLayout();
                        targetDataGrid.ScrollIntoView(targetDataGrid.Items[i]);
                        // TRY TO GET OBJECT AGAIN
                        row = targetDataGrid.ItemContainerGenerator.ContainerFromIndex(i) as DataGridRow;
                    }
 
                    // GET COLUMN COUNT
                    var columnCount = targetDataGrid.Columns.Count;
                    for (int j = 0; j < columnCount; ++j)
                    {
                        // GET CELL OBJECT
                        var elem = targetDataGrid.Columns[j].GetCellContent(row);

                        if (elem == null)
                        {
                            // USE ScrollIntoView() TO THAT COLUMN
                            targetDataGrid.UpdateLayout();
                            targetDataGrid.ScrollIntoView(targetDataGrid.Columns[j]);
                            // TRY TO GET OBJECT AGAIN
                            elem = targetDataGrid.Columns[j].GetCellContent(row);
                        }
 
                        // SET BACKGROUND COLOUR
                        DataGridCell cell = elem.Parent as DataGridCell;
                        string colHeader = targetDataGrid.Columns[j].Header.ToString();
                        string cellData = _viewModel.DictColNameAndValues[colHeader][i];
                        //float actHour = _viewModel.DictValueLists_ActHour[colHeader][i];
 
                        if (8 < float.Parse(cellData))
                        {
                            cell.Background = Brushes.Green;
 
                        }
                        else
                        {
                            cell.Background = Brushes.White;
                        }

用上图,结果是:
1.获取错误,执行ScrollIntoView()后,仍然无法获取单元格值,返回null;
1.当单元格没有错误时,背景颜色赋值有误;(如颜色显示不正确的单元格)
1.一旦我在视图中滚动,所分配的颜色就会移动位置;
1.当我加载~ 1 k+列时,分页变得超级慢和滞后(我觉得这个可能需要创建一个单独的线程来询问)
大概是这样的:

如果datagrid不是最好的方法,是否有其他用户控件或方法来存档我的目标?(当有动态列时,能够分配单元格背景颜色)
有可以试试只要包许可是免费发布的
谢谢你!

  • 2022年10月30日更新 *

向@齐格弗里德.V提出后续问题,答案是:
在这里,我希望我做了一个更好的例子,它更接近我的真实的场景:

它可以显示从第4列开始,列名都是日期
日期范围也将根据每次提取的数据源进行动态填充。这意味着我不能绑定任何静态属性,不像前三列(姓名、首选项和年龄)

nzk0hqpo

nzk0hqpo1#

以下Xaml代码段是从生产代码中复制/粘贴的。其中关键部分是<Style.Triggers>中的绑定“model”PlanningComplete属性:

<DataGrid Grid.Row="2"
                      x:Name="dataGrid"
                      ItemsSource="{Binding CollectionView}"
                      PreviewKeyDown="DataGrid_PreviewKeyDown"
                      IsReadOnly="True">
                <DataGrid.Resources>
                    <Style TargetType="{x:Type DataGridRow}">
                        <EventSetter Event="MouseDoubleClick" Handler="DataGrid_MouseDoubleClick"/>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=PlanningComplete}" Value="True">
                                <Setter Property="Background" Value="LightGreen"/>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=PlanningComplete}" Value="False">
                                <Setter Property="Background" Value="LightYellow"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </DataGrid.Resources>
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding EventName1}"
                                        Header="{Binding Source={x:Static rmc:AppLocalization.Event}}" 
                                        Width="200"/>
                    <DataGridTextColumn Binding="{Binding EventName2}"
                                        Width="80"/>
                    <DataGridTextColumn Binding="{Binding EventDate,Converter={StaticResource DateTimeToLongStringConverter}}"
                                        Header="{Binding Source={x:Static rmc:AppLocalization.Date}}" 
                                        Width="{Binding Source={x:Static rmc:AppConstants.DataGridColumnWidthDateTime}}"/>
                    <DataGridTextColumn Binding="{Binding LocationName1}"
                                        Header="{Binding Source={x:Static rmc:AppLocalization.EventLocation}}" 
                                        Width="190*" MinWidth="190"/>
                </DataGrid.Columns>
            </DataGrid>
ukqbszuj

ukqbszuj2#

您可以像Stefan提供的那样在xaml中完成(但如果我没弄错的话,他的代码是给一整行着色),但我个人更喜欢使用转换器,这样您就可以在所有项目中重用代码,或者更好地在所有解决方案中重用代码,将转换器放在外部库中:
XAML:(您可以选择命名空间和组件)

<Window x:Class="V_CN.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:converters="clr-namespace:`NameSpace`;assembly=`YourAssembly`"
        mc:Ignorable="d"
        Title="YourTitle" >
    

<Window.Resources>
    <converters:ColoringAgeConverter x:Key="coloringAgeConverter" />
</Window.Resources>

您的专栏:

<DataGridTextColumn.ElementStyle>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="Background" Value="{Binding Path="Age" Converter="{StaticResource coloringAgeConverter}"}" />
        </Style>
    </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

然后转换器本身:

public class ColoringAgeConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

    {
        int valInt = Int32.Parse(value.ToString());
        switch (valInt)
        {
            case 1: return "#F0FFE4B5";
            case 2: return "#4000FFFF";
            case 3: return "#407FFF00";
            case 4: return "#907FCC00";
            case 5: return "#C07FCC00";
            case 6: return "#FF0FFF00";
            default: return "#FFFFFFFF";
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

相关问题