DataGrid隐藏列时DisplayIndex读取异常,复制选中单元格遇问题
Oh man, I’ve been there—you get your copy logic working perfectly when all columns are visible, then hide a few and suddenly it’s grabbing the wrong data. Let’s figure out why this happens and how to fix it for good.
Why Your Original Code Breaks With Hidden Columns
The problem boils down to a mismatch between how DisplayIndex works and what’s stored in the ClipboardRowContent collection. When you hide a column, the visual order of remaining columns shifts, but DisplayIndex doesn’t always map cleanly to the position in ClipboardRowContent (which only includes visible columns).
For example: if you have columns Item1 (DisplayIndex 0), Item2 (1), Item3 (2), then hide Item1—Item2’s DisplayIndex becomes 0 and Item3’s becomes 1, which works. But if you hide Item2 instead, Item1 stays at 0 and Item3 stays at 2. Now ClipboardRowContent only has two entries (Item1 and Item3), but your code would try to access index 2 for Item3—resulting in an out-of-bounds error or wrong data.
The Simple Fix: Match by Column Object Instead of Index
Instead of guessing the index, we can directly find the entry in ClipboardRowContent that belongs to the current cell’s column. Here’s the revised code:
private void VwrGrid_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e) { // Get the currently selected column var currentColumn = VwrGrid.CurrentCell.Column; if (currentColumn == null) return; // Find the exact clipboard entry for this column var targetCell = e.ClipboardRowContent.FirstOrDefault(item => item.Column == currentColumn); if (targetCell != null) { e.ClipboardRowContent.Clear(); e.ClipboardRowContent.Add(targetCell); } }
Why This Works
By comparing the Column property of each clipboard entry to our current cell’s column, we skip all the index confusion caused by hidden columns. This directly grabs the data for the exact column the user selected, no matter which columns are visible or hidden.
Backup Plan: Use a Unique Identifier for Columns
If you’re working with a dynamic grid where columns are added/removed frequently, comparing column objects directly might not be reliable. In that case, assign a unique Tag or Name to each column and use that to match:
First, set the unique identifier in your XAML:
<DataGridColumn Tag="Item1" Header="Item 1" ... /> <DataGridColumn Tag="Item2" Header="Item 2" ... /> <DataGridColumn Tag="Item3" Header="Item 3" ... />
Then adjust the copy event code:
private void VwrGrid_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e) { var currentColumn = VwrGrid.CurrentCell.Column; if (currentColumn == null || currentColumn.Tag == null) return; var currentColumnId = currentColumn.Tag.ToString(); var targetCell = e.ClipboardRowContent.FirstOrDefault(item => item.Column.Tag != null && item.Column.Tag.ToString() == currentColumnId); if (targetCell != null) { e.ClipboardRowContent.Clear(); e.ClipboardRowContent.Add(targetCell); } }
Either approach will eliminate the DisplayIndex mismatch issue entirely.
内容的提问来源于stack exchange,提问作者The man holds me down at 1 Rep

