2011-04-13 106 views
10

另一個datagrid鍵綁定問題WPF datagrid和tab鍵

我有一個數據網格。它有選擇模式設置爲FullRow和KeyboardNavigation.TabNavigation =「一次」,我希望能得到我想要的結果,但它沒有。

當數據網格具有焦點時按Tab鍵時,它將一個一個地在網格中的每個列上進行選擇。因此,如果我在具有4列的網格中進行選擇,我將不得不按4次選項卡才能進入下一個tabindex。

我想要的是讓tab鍵在第一次按下時從數據網格中跳出並將焦點放在下一個tabindex上......如果這樣做有道理。

我試圖覆蓋keydown事件處理程序中的tab鍵,就像這樣。

class BetterDataGrid : DataGrid 
{ 
    .............. 
    protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e) 
    { 
    .............. 
    if (e.Key == Key.Tab) 
    { 
     Console.WriteLine("TAB"); 
     MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); 
    } 
    ......... 
    } 

它確實將「TAB」寫入控制檯,但該選項卡仍保持其默認行爲。不知道這是否是進入下一個tabindex的正確方式,但是這應該使tab鍵不會做任何事情,而是寫入控制檯或導致異常。
使我認爲覆蓋標籤鍵行爲是不可能的。

希望得到一些有用的意見。
一如既往,在此先感謝。

回答

9

我希望這是我的業務線軟件,我發現解決它的唯一方法是通過代碼隱藏,使用DataGrid的PreviewKeyDown,GotKeyboardFocus和LostKeyboardFocus事件。我已經將這些事件處理程序放在WPF裝飾器中,以避免爲每個DataGrid重複它。 DataGrid子類可能是可能的,但我沒有嘗試過。

的處理程序的代碼如下(數據網格爲x:名稱=「網格」對於本示例代碼):

 private IInputElement lastDataGridFocus = null; 
    private int selectedcolumnindex = 0; 

    void grid_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) 
    { 
     if (grid.Items.Count > 0 && (e.NewFocus is DataGrid || (e.NewFocus is DataGridCell && !(e.OldFocus is DataGridCell)))) 
     { 
      DataGridCell cell = null; 

      if (lastDataGridFocus != null) 
      { 
       FocusManager.SetFocusedElement(grid, lastDataGridFocus); 
       lastDataGridFocus = null; 
       e.Handled = true; 
       return; 
      } 

      if (grid.SelectedCells.Count == 0) 
      { 
       DataGridRow rowContainer = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(0); 
       if (rowContainer != null) 
       { 
        DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer); 
        cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex((selectedcolumnindex < 0) ? 0 : selectedcolumnindex); 
       } 
      } 
      else 
      { 
       DataGridCellInfo selectedDataGridCellInfo = (grid.SelectedCells[0] as DataGridCellInfo?).Value; 
       DataGridRow rowContainer = (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(selectedDataGridCellInfo.Item); 
       if (rowContainer != null) 
       { 
        DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer); 
        cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex((selectedcolumnindex < 0) ? 0 : selectedcolumnindex); 
       } 
      } 
      if (null != cell) 
      { 
       FocusManager.SetFocusedElement(grid, cell as IInputElement); 
       e.Handled = true; 
      } 
     } 
    } 

    void grid_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) 
    { 
     if (!(e.NewFocus is DataGridCell)) 
     { 
      if (grid.CurrentCell != null) 
      { 
       selectedcolumnindex = grid.Columns.IndexOf(grid.CurrentCell.Column); 
      } 
     } 
    } 

    void grid_PreviewKeyDown(object sender, KeyEventArgs e) 
    { 
     if (Keyboard.Modifiers == ModifierKeys.Shift && e.Key == Key.Tab) 
     { 
      lastDataGridFocus = Keyboard.FocusedElement; 
      grid.MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous)); 
      e.Handled = true; 
     } 
     else if (Keyboard.Modifiers == ModifierKeys.None && e.Key == Key.Tab) 
     { 
      lastDataGridFocus = Keyboard.FocusedElement; 
      grid.MoveFocus(new TraversalRequest(FocusNavigationDirection.Last)); 
      (Keyboard.FocusedElement as FrameworkElement).MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); 
      e.Handled = true; 
     } 
    } 

有了這個代碼可以使用光標鍵將網格內導航,並Tab鍵和Shift-Tab鍵讓你走出數據網格。如果您退出網格並返回網格,您也會到達您離開的同一個單元格。這是我的用戶和我想要的,這是恕我直言,DataGrid控件應該提供什麼作爲默認行爲。

+1

抱歉,遲到的接受,沒有得到測試的機會,但這是好的。謝謝 – 2011-05-18 00:14:27

-2

你試圖達到的目標不是正確的行爲,每個人都希望當DataGrid專注時按下Tab鍵的時候Excel就像導航一樣。如果您不希望用戶瀏覽DataGrid,最好通過在DataGrid上設置IsTabStop="False"來防止DataGrid上的製表位停止。

+3

爲什麼選擇倒票?這只是我從UX角度看的意見! – 2011-04-13 21:11:39

+1

是的,我同意你Fadil先生,最好是設置IsTabStop =「False」 – 2011-04-13 21:15:24

+2

對不起,但你的回答並沒有真正的幫助。 IsTabStop = false會將選項卡帶入網格中,我希望保留網格,並且在重點關注時不會產生所需的行爲。很多情況下,Excel風格的導航運行良好,但在這種情況下,它只是多餘的,網格是隻讀的,並且具有全行選擇。 – 2011-04-13 21:33:54