2014-03-24 3 views
1

Мне нужно реализовать функцию «копировать значение в буфер обмена» для WPF DataGrid, которая должна быть доступна по всем общим каналам: пункт контекстного меню правой кнопкой мыши; пункт меню контекстного меню; Ctrl + C. Содержимое сетки данных происходит от привязки данных, но поскольку команда копирования является видом, доступной только для просмотра, она полностью реализована в уровне представления, а не в режиме просмотра. Поэтому я не использую ICommand для этого, а только обработчики событий в коде.Найти сфокусированную ячейку из DataGrid

Узел выбора DataGrid установлен на FullRow, но клавиши навигации по стрелке все еще работают, и прямоугольник фокусировки можно увидеть для отдельных ячеек. Таким образом, одна ячейка может быть сфокусирована, пока выбрана полная строка. Для этой команды мне нужно определить сфокусированную ячейку.

Элемент меню уже довольно сложный. Событие Click вызывает экземпляр MenuItem, из которого я могу перейти к ContextMenu и далее к DataGrid. Вот и все, без щелчка. Я уже знаю, как получить DataGrid, есть только один из них, видимый за раз.

Теперь мне нужно выяснить, какая ячейка сосредоточена. Но я даже не могу получить список выбранных ячеек или строк или даже всех строк. Все свойства, которые я могу найти, просто указывают на некоторые фрагменты информации, а DataGrid.Rows просто не существует. Я мог бы сканировать все визуальное дерево для некоторых сфокусированных DataGridCell, но это, вероятно, не очень эффективно.

Любые идеи?

Позже мне также понадобится вторая функция «скопировать выбранные строки в буфер обмена», которая копирует значения из всех ячеек во всех выбранных строках в формате, который можно вставить в Excel (линии с разделителями табуляции).

ответ

2

вспомогательную функцию:

/// <summary> 
    /// Look for child element 
    /// </summary> 
    /// <typeparam name="childItem">Child Item</typeparam> 
    /// <param name="obj">Dependency Object</param> 
    /// <returns>The child or null</returns> 
    private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject 
    { 
     if (obj == null) 
     { 
      return null; 
     } 

     int childCount = VisualTreeHelper.GetChildrenCount(obj); 

     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(obj, i); 

      if (child != null && child is childItem) 
      { 
       return (childItem)child; 
      } 
      else 
      { 
       childItem childOfChild = this.FindVisualChild<childItem>(child); 

       if (childOfChild != null) 
       { 
        return childOfChild; 
       } 
      } 
     } 

     return null; 
    } 

После загрузки DataGrid, вы можете назвать это:

/// <summary> 
    /// Get the cell of the datagrid. 
    /// </summary> 
    /// <param name="dataGrid">The data grid in question</param> 
    /// <param name="cellInfo">The cell information for a row of that datagrid</param> 
    /// <param name="cellIndex">The row index of the cell to find. </param> 
    /// <returns>The cell or null</returns> 
    private DataGridCell TryToFindGridCell(DataGrid dataGrid, DataGridCellInfo cellInfo, int cellIndex = -1) 
    { 
     DataGridRow row; 
     DataGridCell result = null; 

     if (cellIndex < 0) 
     { 
      row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromItem(cellInfo.Item); 
     } 
     else 
     { 
      row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(cellIndex); 
     } 

     if (row != null) 
     { 
      int columnIndex = dataGrid.Columns.IndexOf(cellInfo.Column); 

      if (columnIndex > -1) 
      { 
       DataGridCellsPresenter presenter = this.FindVisualChild<DataGridCellsPresenter>(row); 

       if (presenter != null) 
       { 
        result = presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex) as DataGridCell; 
       } 
       else 
       { 
        result = null; 
       } 
      } 
     } 

     return result; 
    } 

Затем после того, как вы получите вашу клетку, просто проверить IsFocused собственности.

+1

спасибо. Это позволило найти содержание сфокусированной клетки. К сожалению, я обнаружил, что щелкнутая ячейка только сфокусирована, если ранее не была выбрана строка. При щелчке правой кнопкой мыши по другой ячейке в той же строке фокус не перемещается, и я получаю неправильную ячейку. Но это проблема моего первоначального вопроса. – ygoe

+0

Интересно. Интересно, не могли бы вы UnSelect строки ...? Возможно, это немного позже. – ouflak

+0

Я изменил этот код тем временем. Я использую только сфокусированную ячейку в качестве основы, если нажата клавиша Apps, затем я открываю контекстное меню прямо под ячейкой. При щелчке правой кнопкой мыши я использую e.OriginalSource и найдите родителя DataGridCell в визуальном дереве. В этом случае я также открываю контекстное меню прямо под ячейкой. Только если ячейка не найдена, используется позиция мыши. – ygoe

Смежные вопросы