【问题标题】:WPF Datagrid cell coloringWPF Datagrid 单元格着色
【发布时间】:2015-12-17 05:22:35
【问题描述】:

我们如何在 WPF 数据网格中以编程方式为单元格添加颜色?我可以逐行添加颜色,但我想从后面的代码为单元格添加颜色。请提供代码?

【问题讨论】:

    标签: wpf datagrid


    【解决方案1】:

    此代码的作用:首先,您处理LoadingRow 事件,获取行(它具有保存绑定项目的 Item 属性),获取绑定项目,进行所有需要的计算,获取您需要的单元格改变并最终改变目标单元格的样式。

    这是代码(作为项目,我使用带有 int ID 属性的示例对象,用于着色)。:

    C#:

    private void FillTheDataGrid()
    {
        List<SomeClass> list = new List<SomeClass>();
        Random rnd = new Random();
        for (int i = 0; i < 10; i++)
        {        
           list.Add(new SomeClass() { DaysOld = DateTime.Now.Add(new TimeSpan(rnd.Next(5), 0, 0, 0)), ID=i});
         }
         dataGrid.ItemsSource = list;
    }
    
    private void dataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => AlterRow(e)));
    }
    
    private void AlterRow(DataGridRowEventArgs e)
    {
        var cell = GetCell(dataGrid, e.Row, 1);
        if (cell == null) return;
    
        var item = e.Row.Item as SomeClass;
        if (item == null) return;
    
        var value = item.ID;
    
        if (value <= 1) cell.Background = Brushes.Red;
        else if (value <= 2) cell.Background = Brushes.Yellow;
        else cell.Background = Brushes.Green;
    }
    
    public static DataGridRow GetRow(DataGrid grid, int index)
    {
        var row = grid.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;
    
        if (row == null)
        {
            // may be virtualized, bring into view and try again
            grid.ScrollIntoView(grid.Items[index]);
            row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
        }
        return row;
    }
    
    public static T GetVisualChild<T>(Visual parent) where T : Visual
    {
        T child = default(T);
        int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < numVisuals; i++)
        {
            var v = (Visual)VisualTreeHelper.GetChild(parent, i);
            child = v as T ?? GetVisualChild<T>(v);
            if (child != null)
            {
                break;
            }
        }
        return child;
    }
    
    public static DataGridCell GetCell(DataGrid host, DataGridRow row, int columnIndex)
    {
        if (row == null) return null;
    
        var presenter = GetVisualChild<DataGridCellsPresenter>(row);
        if (presenter == null) return null;
    
        // try to get the cell but it may possibly be virtualized
        var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
        if (cell == null)
        {
            // now try to bring into view and retreive the cell
            host.ScrollIntoView(row, host.Columns[columnIndex]);
            cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
        }
        return cell;
    }
    

    型号:

    public class SomeClass
    {
        public int ID { get; set; }
        public DateTime DaysOld { get; set; }
    }
    

    XAML:

    <DataGrid Name="dataGrid" AutoGenerateColumns="True" LoadingRow="dataGrid_LoadingRow"/>
    

    【讨论】:

    • @RintoAntony 如果我的回复对您有帮助,可以将其标记为答案以简化对其他人的搜索。
    • 太棒了!几个恕我直言:1)没有列虚拟化,看起来不需要带有 ScrollIntoView 的分支,2)在现实生活中通常有更多列,并且由于我们正在处理整行,因此为每个重复 GetVisualChild 是没有意义的行中的单元格 - 将是相同的。
    • @sarh 随时添加您编辑的答案!:) 请通知我您发布了新答案!我会为答案投票。
    • 谢谢,但我认为这不公平。您的答案包含使其工作所需的一切,我刚刚分享了一些优化想法,我什至不确定它会明显更快。而且我不喜欢在我回答后看到另一个几乎相同的问题,只是有些花里胡哨。
    【解决方案2】:

    我遇到了同样的问题,终于找到了答案,比我想象的要容易,这里是更改单元格颜色的代码:

    DataGridRow firstRow = dataGrid.ItemContainerGenerator.ContainerFromItem(dataGrid.Items[i]) as DataGridRow; 
    firstColumnInFirstRow = dataGrid.Columns[j].GetCellContent(firstRow).Parent as DataGridCell;
    firstColumnInFirstRow.Background = Brushes.IndianRed;
    

    【讨论】:

      【解决方案3】:

      根据 DataGridCell 中的内容,您可以创建一个绑定到颜色或使用触发器的 DataTemplate

      <DataTemplate DataType="{x:Type cell:MyCellObject}"> 
          <TextBlock TextAlignment="Center" Text="{Binding Text}">
              <TextBlock.Style>
                  <Style TargetType="TextBlock">
                      <Setter Property="Background" Value="{Binding MyBackground}" />
                      <Setter Property="Foreground" Value="Black" />
                      <Setter Property="Padding" Value="0" />
      
                      <Style.Triggers>    
                          <DataTrigger Binding="{Binding MyBool}" Value="True">
                              <Setter Property="Foreground" Value="DarkRed" />
                              <Setter Property="FontWeight" Value="Bold" />
                          </DataTrigger>
                      </Style.Triggers>
      
                 </Style>
              </TextBlock.Style>
          </TextBlock>
      </DataTemplate>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-07
        • 1970-01-01
        • 2017-04-22
        • 1970-01-01
        • 1970-01-01
        • 2011-07-01
        • 2012-04-30
        • 2016-01-23
        相关资源
        最近更新 更多