【问题标题】:Looping Through WPF DataGrid Using foreach使用 foreach 循环遍历 WPF DataGrid
【发布时间】:2013-03-17 10:41:23
【问题描述】:

所有,我正在尝试使用 for each 循环遍历 WPF DataGrid 以更改错误单元格的背景颜色。我检查了很多问题,但我还没有找到足够的答案。到目前为止我所拥有的是

public void RunChecks()
{
    const int baseColumnCount = 3;
    foreach (DataRowView rv in dataGrid.Items)
    {
        for (int i = baseColumnCount; i < dataGrid.Columns.Count; i++)
        {
            if (!CheckForBalancedParentheses(rv.Row[i].ToString()))
            {
                Color color = (Color)ColorConverter.ConvertFromString("#FF0000");
                row.Background = new SolidColorBrush(color); // Problem!
            }
        }
    }
}

问题是,为了更改DataGrid 中一行的Background 颜色,我需要使用与DataRowView rv 关联的DataGridRow 对象。

如何从对象rv (DataRowView) 中获取对DataGridRow 的引用?

感谢您的宝贵时间。

编辑。根据下面的建议,我现在有以下样式,它适用于鼠标悬停事件并设置相关单元格的前后字体。但是,对于如何在上面的代码中在运行时将背景色应用于单元格,我真的很迷茫。 XML 样式是

<Window.Resources>
    <Style TargetType="{x:Type DataGridRow}">
        <Style.Triggers>
            <Trigger Property="IsMouseOver"
                     Value="True">
                <Setter Property="Background" Value="Red" />
                <Setter Property="FontWeight" Value="ExtraBold" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

【问题讨论】:

    标签: c# wpf datagrid type-conversion


    【解决方案1】:
    //the Class that resembles the Datagrid Item schema
    
    foreach (Class cl in dgDatagrid.Items)
       {
           MessageBox.Show(cl.ID.ToString());
       }
    
    this is the most simplest way to read the datagrid data
    most articles misguide such simple things
    

    【讨论】:

      【解决方案2】:

      “Killercam”的答案对我有用,但我需要补充:

      myDataGrid.UpdateLayout();

      在使用 GetCell 方法之前,我确定我没有得到空引用。

      要获得整个 Helper 类,请查看 DataGridHelper

      在经历了这么多痛苦之后,我尝试了整个代码,但我遇到了另一个问题,即正确颜色的单元格在滚动期间发生了变化,解决方案是启用虚拟化并将其模式设置为标准。

      VirtualizingStackPanel.IsVirtualizing="True"
      VirtualizingStackPanel.VirtualizationMode="Standard"
      

      所以,希望这对需要遍历数据网格单元格的任何人有所帮助。

      【讨论】:

        【解决方案3】:

        经过大量阅读,我找到了一种方法来做我想做的事 - 根据特定条件在运行时为单元格着色。这是我用来上色的方法

        public void RunChecks()
        {
            const int baseColumnCount = 3;
            for (int i = baseColumnCount; i < dataGrid.Columns.Count; i++)
            {
                foreach (DataGridRow row in Utilities.GetDataGridRows(dataGrid))
                {
                    if (row != null)
                    {
                        DataGridCell cell = dataGrid.GetCell(row, i);
        
                        // Start work with cell.
                        Color color;
                        TextBlock tb = cell.Content as TextBlock;
                        string cellValue = tb.Text;
                        if (!CheckForBalancedParentheses(cellValue))
                            color = (Color)ColorConverter.ConvertFromString("#FF0000");
                        else
                            color = (Color)ColorConverter.ConvertFromString("#FFFFFF");
                        row.Background = new SolidColorBrush(color);
                        //cell.Background = new SolidColorBrush(color);
                    }
                }
            }
        }
        

        这些是所需的相关实用方法

        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++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
                child = v as T;
                if (child == null)
                    child = GetVisualChild<T>(v);
                if (child != null)
                    break;
            }
            return child;
        }
        
        public static DataGridCell GetCell(this DataGrid grid, DataGridRow row, int column)
        {
            if (row != null)
            {
                DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(row);
                if (presenter == null)
                {
                    grid.ScrollIntoView(row, grid.Columns[column]);
                    presenter = GetVisualChild<DataGridCellsPresenter>(row);
                }
                DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
                return cell;
            }
            return null;
        }
        
        public static IEnumerable<DataGridRow> GetDataGridRows(DataGrid grid)
        {
            var itemsSource = grid.ItemsSource as IEnumerable;
            if (null == itemsSource) yield return null;
            foreach (var item in itemsSource)
            {
                var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
                if (null != row) yield return row;
            }
        }
        

        但是请注意,当用户滚动时,单元格的颜色会从一个单元格移动到另一个单元格!?这是 WPF 的另一个令人惊奇的烦恼。我真的很困惑为什么这么简单的事情会变得如此困难。我们需要为这种事情使用 MVVM 类型模式的建议我觉得很神奇......

        我希望这对其他人有帮助。

        【讨论】:

          【解决方案4】:

          您可以使用ItemContainerGenerator 获取数据的可视化表示,即DataGridRow -

          DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator
                                                 .ContainerFromItem(rv);
          

          【讨论】:

          • 这是为row 返回null。我检查了rv,这是非空的。很抱歉再次打扰您,感谢您的宝贵时间...
          • 这将返回null 仅在您的 GUI 上尚未呈现行的情况下。您正在处理多少行并且在您的网格上启用了virtualisation
          • 链接在这里 - stackoverflow.com/questions/6713365/… 可能对你有帮助。
          • 目前从 1 行到 1000 行不等,所以在计划中并不多。我不熟悉DataGridVisulisation 属性。我试图用 XML 编写它,但我可以看到一个具有此名称的属性...再次感谢。
          • 尝试在您的数据网格VirtualizingStackPanel.IsVirtualizing="False" 上设置它,如上面提供的链接中所述。但是,这样做的代价是一次渲染所有 1000 行。
          【解决方案5】:

          使用 WPF 时,始终避免直接访问 UI 工件。

          在您的 ModelView 中创建属性 Color,并将其绑定到 DataGrid 视图的单行模板的背景颜色。

          因此,为了更改颜色,您将循环抛出 ModelView 集合并设置/读取绑定到每一行的每个对象的 Color 属性。通过更改它,如果绑定设置正确,您将影响行 UI 颜色外观。

          具体样品可以看:

          How do I bind the background of a data grid row to specific color?

          【讨论】:

          • 感谢您的宝贵时间。我会听取您的建议并开始阅读。我也一直在尝试为整个专栏着色,但同样没有运气。我已经问了另一个问题here,如果您可以接受并想要代表。再次感谢...
          • @Killercam:行和列的想法是一样的。如果 UI 对象提供了可以通过直接访问或绑定更改的某些属性(在本例中为颜色),则您可以使用模型视图对象中的绑定。
          • 谢谢。在阅读了关于样式、触发器等的书的一章后。我现在已经在鼠标悬停事件上改变了行的颜色。但是,我不知道如何在运行时使用这些样式将单元格/行更改为代码中所需的颜色。如果您能在这里提供任何帮助,将不胜感激...我已经编辑了问题以展示我的风格。
          • @Killercam:看这里:stackoverflow.com/questions/5030361/…,希望对您有所帮助。不幸的是,这不是可以在问答网站的简单回答中描述的东西。在模型视图颜色属性中定义DataModel、ModelView,在XAML中绑定,在运行时访问modelview对象及其属性来影响UI。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-13
          • 1970-01-01
          • 1970-01-01
          • 2013-12-16
          • 2011-05-25
          相关资源
          最近更新 更多