2013-03-27 152 views
6

所有,我试图循环WPF DataGrid使用每个循环来改变错误的单元格的背景颜色。我检查了很多问题,但我还没有找到足够的答案。我至今是通过WPF DataGrid循环使用foreach

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

的问题是,为了改变Background颜色排在我DataGrid我需要与DataRowViewrv ascociated的DataGridRow对象的工作。

如何从对象rvDataRowView)中获得对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> 

回答

5

当你使用WPF直接合作,避免总是访问UI工件。

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

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

对于具体的例子中,你可以看一下:

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

+0

谢谢你的时间。我会接受你的建议并开始阅读。我也一直在尝试颜色和整个专栏,再次没有运气。我问另一个问题[这里](http://stackoverflow.com/questions/15644105/change-the-background-color-of-entire-column-of-wpf-datagrid-at-runtime),如果你可以被遗忘并希望代表。再次感谢... – MoonKnight 2013-03-27 11:18:46

+0

@Killercam:这个想法对于行和列是一样的。如果UI对象提供了一些可以通过直接访问或通过绑定进行更改的属性(本例中为颜色),则可以使用您的模型视图对象中的绑定。 – Tigran 2013-03-27 11:25:54

+0

谢谢。阅读了关于样式,触发器等书的章节,现在我已经在鼠标悬停事件上获得了行更改颜色。但是,我失去了如何在运行时使用这些样式将单元格/行更改为代码所需的颜色。如果你可以在这里提供任何帮助,将不胜感激...我编辑了这个问题来展示我的风格。 – MoonKnight 2013-03-27 12:29:47

2

可以使用ItemContainerGenerator来获得视觉表现为您的数据,即DataGridRow -

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

这是为'行'返回'null'。我检查'rv',这是非空的。对不起,再次打扰你,感谢你的时间...... – MoonKnight 2013-03-27 11:17:21

+0

这将返回'null',以防在你的GUI上还没有渲染行。您正在处理的行数是多少,并且在您的网格上启用了“虚拟化”功能? – 2013-03-27 11:19:55

+0

链接在这里 - http://stackoverflow.com/questions/6713365/itemcontainergenerator-containerfromitem-returns-null可能是你的帮助。 – 2013-03-27 11:23:15

0

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

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型模式来寻找这种令人惊叹的东西...

我希望这可以帮助别人。

1

“Killercam”的回答为我工作,但我需要添加:

myDataGrid.UpdateLayout();

使用GetCell方法,所以我敢肯定,我没有得到一个空引用之前。

获得辅助类的外观整体处于DataGridHelper

后,所有的痛苦,我尝试了整个代码,我面临的另一个probem至极的是,滚动过程中改变了正确颜色的细胞,该解决方案是使虚拟化并将其模式设置为标准。

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

所以,希望这将有助于任何人需要迭代通过datagrid单元格。

0
//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 
+0

这不会提供问题的答案。一旦你有足够的[声誉](https://stackoverflow.com/help/whats-reputation),你将可以[对任何帖子发表评论](https://stackoverflow.com/help/privileges/comment);相反,[提供不需要提问者澄清的答案](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-c​​an- I-DO-代替)。 - [来自评论](/ review/low-quality-posts/17321773) – 2017-09-13 18:35:36