2013-03-27 157 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