2012-11-13 50 views
2

我需要在用戶點擊它時摺疊WPF DataGrid的細節行,並在他們再次點擊時重新顯示它。我也想使用單選來保留VisibleWhenSelected的DataGridRoDetailsVisibilityMode。WPF datagrid在點擊時摺疊細節行

我想出了這個解決方案,基於關閉這個帖子在別處:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0a45b3a7-46d0-45a9-84b2-0062f07f6fec#eadc8f65-fcc6-41df-9ab9-8d93993e114c

private bool _rowSelectionChanged; 


    private void dgCompletedJobs_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     _rowSelectionChanged = true; 
    } 

    private void dgCompletedJobsMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) 
    { 
     DependencyObject dep = (DependencyObject)e.OriginalSource; 

     //navigate up the tree 
     while (dep != null && 
      !(dep is DataGridCell) && 
      !(dep is DataGridColumnHeader)) 
     { 
      dep = VisualTreeHelper.GetParent(dep); 
     } 

     if (dep == null) 
     { 
      return; 
     } 

     DataGridCell dgc = dep as DataGridCell; 
     if (dgc != null) 
     { 
      //navigate further up the tree 
      while (dep != null && !(dep is DataGridRow)) 
      { 
       dep = VisualTreeHelper.GetParent(dep); 
      } 

      DataGridRow dgr = dep as DataGridRow; 
      DataGrid dg = sender as DataGrid; 
      if (dg != null && dgr != null) 
      { 
       if (dgr.IsSelected && !_rowSelectionChanged) 
       { 
        dg.RowDetailsVisibilityMode = 
         (dg.RowDetailsVisibilityMode == DataGridRowDetailsVisibilityMode.VisibleWhenSelected) 
          ? DataGridRowDetailsVisibilityMode.Collapsed 
          : DataGridRowDetailsVisibilityMode.VisibleWhenSelected; 
       } 
       else 
       { 
        dg.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.VisibleWhenSelected; 
       } 
      } 
     } 
     _rowSelectionChanged = false; 
    } 

這似乎很好地解決我的問題,但我有一個令人難忘的懷疑,這可能是更簡單和優雅的完成,特別是因爲我在這個項目上使用MVVM。但是,我認爲這是事件驅動代碼隱藏的可接受使用方式,因爲它純粹是表示邏輯。

有沒有人有更清潔的解決方案?

回答

1

爲什麼不使用發件人參數?如果事件在DataGrid上定義,發件人始終是DataGrid!使用安全的cast來檢查null是否安全,但是這應該可以做到。

代碼似乎不必要的複雜,因爲您正在通過可視化樹從原始源回到您的DataGrid。

 private void dataGridMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
    { 
     DataGrid dg = sender as DataGrid; 
     if (dg == null) 
      return; 
     if (dg.RowDetailsVisibilityMode == DataGridRowDetailsVisibilityMode.VisibleWhenSelected) 
      dg.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Collapsed; 
     else 
      dg.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.VisibleWhenSelected; 
    } 
5

要與「正確」的MVVM做到這一點,你應該RowDetailsVisibilityMode綁定到視圖模型屬性:

<DataGrid x:Name="dgCompletedJobs" RowDetailsVisibilityMode="{Binding RowDetailsVisible}"/> 

您的視圖模型屬性會是這樣的:

private DataGridRowDetailsVisibilityMode _rowDetailsVisible; 
public DataGridRowDetailsVisibilityMode RowDetailsVisible 
{ 
    get { return _rowDetailsVisible; } 
    set { 
     _rowDetailsVisible = value; 
     if (PropertyChanged != null) { 
      PropertyChanged(this, new PropertyChangedEventArgs("RowDetailsVisible")); 
     } 
    } 
} 

要將鼠標點擊事件鏈接到屬性更改,您可以執行一些特殊的附加行爲,如here所示,或者僅使用後面的代碼來調用t他直接觀看模型(我經常這樣做我自己簡單的任務):

private void dgCompletedJobsMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) 
{ 
    Window1ViewModel viewModel = (Window1ViewModel)DataContext; 
    if (viewModel.RowDetailsVisible == DataGridRowDetailsVisibilityMode.Collapsed) { 
     viewModel.RowDetailsVisible = DataGridRowDetailsVisibilityMode.VisibleWhenSelected; 
    } else { 
     viewModel.RowDetailsVisible = DataGridRowDetailsVisibilityMode.Collapsed; 
    } 
} 
+0

工作完美。謝謝。 – GeoffCoope

0

我想出了一個不同的方式,但不是一個「正確」的MVVM方式,因爲它使用的代碼背後(如做一些代碼在上面提出的答案中),但它只需幾行代碼即可實現。

通過對PreviewMouseUp事件進行編碼,我能夠得到我需要的確切行爲。該代碼確保您實際上點擊了網格中的某些內容,並將其摺疊爲必須是已打開的同一行。

private void UIElement_OnPreviewMouseDown(object sender, MouseButtonEventArgs e) 
    { 
     DataGrid grid = sender as DataGrid; 

     if (grid != null) 
     { 
      FrameworkElement element = e.OriginalSource as FrameworkElement; 

      if (element?.DataContext is MyCustomObject) 
      { 
       if (grid.SelectedItem == (MyCustomObject) ((FrameworkElement) e.OriginalSource).DataContext) 
       { 
        grid.SelectedIndex = -1; 
        e.Handled = true; 
       } 
      } 
     } 
    }