2017-09-25 86 views
1

我有DataGrid,在每个DataGridRow我有行详细信息,其中包含几个控件。如何停止DataGridRow选择如果在RowDetails中点击鼠标

我想要什么,如果有的话则点击该行的细节里面:
- 不选择该行,或者更准确地说,
- 更改现有DataGrid选择。

我正在考虑处理PreviewMouseDown和MouseDown事件的行为,不知怎的,使DataGrid跳过选择过程,但不知道如何继续。

最后,我将在具有更多信息的细节中使用TabControl,因此我也不希望TabItem单击来更改DataGrid的现有选择。

会不会有一种方法来启动PreviewMouseDown的隧道在电网“DetailsContainer”级别和网格“DetailsContainer”停止的MouseDown的冒泡水平

<DataGrid Name="dgAudit" 
      CanUserReorderColumns="False" 
      CanUserAddRows="False" 
      CanUserDeleteRows="False" 
      CanUserResizeColumns="False" 
      CanUserResizeRows="False" 
      CanUserSortColumns="False" 
      IsReadOnly="True" 
      ItemsSource="{Binding GEOM_ASSET_OC_LIST}" 
      VirtualizingPanel.ScrollUnit="Pixel" 
      RowDetailsVisibilityMode="Visible" 
      > 
    <i:Interaction.Behaviors> 
     <behaviors:DataGridBehaviors /> 
    </i:Interaction.Behaviors> 

    <DataGrid.Columns> 
     <DataGridTextColumn Header="Asset ID" Binding="{Binding ASSET_ID}" Width="200" /> 
     <DataGridTextColumn Header="Asset Type" Binding="{Binding ASSET_TYPE}" Width="200" /> 
     <DataGridTextColumn Header="Last Update By" Binding="{Binding LAST_UPDATE_BY}" Width="150" /> 
     <DataGridTextColumn Header="Last Update Date" Binding="{Binding LAST_UPDATE_DATETIME, StringFormat=\{0:dd.MM.yy HH:mm:ss tt\}}" Width="150" /> 
    </DataGrid.Columns> 
    <DataGrid.RowDetailsTemplate> 
     <DataTemplate> 
      <Grid Name="DetailsContainer"> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="*" /> 
        <ColumnDefinition Width="Auto" /> 
       </Grid.ColumnDefinitions> 
       <TextBlock Name Text="{Binding Notes}" Width="400" HorizontalAlignment="Left" TextWrapping="Wrap"/> 
       <Button Content="Button" Grid.Column="1" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/> 
      </Grid> 
     </DataTemplate> 
    </DataGrid.RowDetailsTemplate> 
</DataGrid> 

只是一个快速模拟出一个空的行为

public class DataGridBehaviors : Behavior<DataGrid> 
{ 
    protected override void OnAttached() 
    { 
     base.OnAttached(); 
     this.AssociatedObject.MouseDown += DataGrid_MouseDown; 
     this.AssociatedObject.PreviewMouseDown += DataGrid_PreviewMouseDown; 
    } 

    protected override void OnDetaching() 
    { 
     this.AssociatedObject.PreviewMouseDown -= DataGrid_PreviewMouseDown; 
     this.AssociatedObject.MouseDown -= DataGrid_MouseDown; 
     base.OnDetaching(); 
    } 

    private void DataGrid_MouseDown(object sender, MouseButtonEventArgs e) 
    { 
    } 

    private void DataGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
    { 
     DependencyObject obj = (DependencyObject)e.OriginalSource; 
     DataGridDetailsPresenter RowsDetails = FindParent<DataGridDetailsPresenter>(obj); 
     if (RowsDetails != null) 
     { 
      //Skip over selection, maybe temporarily removed native selection handler??? 
     } 
    } 

    public static T FindParent<T>(DependencyObject child) where T : DependencyObject 
    { 
     //get parent item 
     DependencyObject parentObject = VisualTreeHelper.GetParent(child); 

     //we've reached the end of the tree 
     if (parentObject == null) return null; 

     //check if the parent matches the type we're looking for 
     T parent = parentObject as T; 
     if (parent != null) 
      return parent; 
     else 
      return FindParent<T>(parentObject); 
    } 

    private static T GetVisualChild<T>(DependencyObject 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; 
    } 
} 
+0

可能包括写只读属性设置为“真” –

回答

0

我发现了另一种可能的解决方法。通过在DataGridRowHeader内部创建一个小的Canvas,然后在下一个子容器设置ClipsToBoundsfalse。然后,它不包含标题,但也可以在不影响DataGrid的当前选择的情况下点击。这是绑定到行细节的IsExpanded,看起来是部分。

警告一句话是,如果行详细信息包含大量数据,并且代码如下所示,可能效率非常低,加载时间和滚动延迟。取决于是否使用virtualization。这些数据将与该行同时加载,并且可能效率很低,因为这些控件在RowDetailsTemplate中时会按需加载。可能最好是严格控制通过User Control或动态加载此数据。

另外,您可能需要听取DataGridLayoutUpdated事件以调整详细控件的宽度。

<DataGrid.RowHeaderTemplate> 
    <DataTemplate> 
     <Grid> 
      <Expander Template="{StaticResource StretchyExpanderTemp}" 
         OverridesDefaultStyle="True" 
         Header="" 
         HorizontalAlignment="Right" 
         VerticalAlignment="Top" 
         Expanded="Expander_Expanded" Collapsed="Expander_Collapsed" 
         IsExpanded="{Binding DataContext.IsExpanded, RelativeSource={RelativeSource AncestorType=DataGridRowHeader}}" /> 

      <Canvas Background="BlueViolet" 
        Width="5" 
        VerticalAlignment="Top" 
        HorizontalAlignment="Left" 
        Height="5"> 
       <TabControl Name="tcAA" 
          TabStripPlacement="Left" 
          Margin="20,18,0,0" 
          Height="185" 
          Width="500" 
          VerticalAlignment="Top" 
          HorizontalAlignment="Left" 
          ItemsSource="{Binding DataContext.AAUDIT, RelativeSource={RelativeSource AncestorType=DataGridRowHeader}}" 
          SelectedIndex="0" 
          ClipToBounds="False" 
          Visibility="{Binding DataContext.IsExpanded, RelativeSource={RelativeSource AncestorType=DataGridRowHeader}, Converter={StaticResource bool2VisibilityConverter}}" 
          > 
        ... 
        <TabControl.ItemTemplate> 
         <DataTemplate> 
          <Grid> 
           <TextBlock Text="{Binding DISPLAY_NAME}" /> 
          </Grid> 
         </DataTemplate> 
        </TabControl.ItemTemplate> 
        <TabControl.ContentTemplate> 
         <DataTemplate> 
          ... 
         </DataTemplate> 
        </TabControl.ContentTemplate> 
       </TabControl> 
      </Canvas> 
     </Grid> 
    </DataTemplate> 
</DataGrid.RowHeaderTemplate> 

<DataGrid.RowDetailsTemplate> 
    <DataTemplate> 
     <Grid Height="185" > 
     </Grid> 
    </DataTemplate> 
</DataGrid.RowDetailsTemplate> 

因为它站在这里是什么我生产一个简单的例子: enter image description here

1

不幸的是,目前的WPF DataGrid的实现,这是不可能实现你想要什么。

DataGridDetailsPresenter寄存器使用EventManager API的MouseLeftButtonDownEvent路由事件class event handler

EventManager.RegisterClassHandler(
    typeof(DataGridDetailsPresenter), 
    MouseLeftButtonDownEvent, 
    new MouseButtonEventHandler(OnAnyMouseLeftButtonDownThunk), 
    true); 

注意,它被设置为true最后一个参数。这是一个标志,指示听众是否想要了解已处理的事件。在这种情况下,即使您在任何级别将RoutedEventArgs.Handled属性设置为true,仍然会调用内部DataGridDetailsPresenter的事件处理程序。

此事件处理程序负责将DataRow聚焦在单击详细信息视图中。你一定知道,在WPF中,类事件处理程序在实例事件处理程序之前被调用。因此,左侧点击一个详细信息行的演示者会发生的第一件事是包含行(实际上,该行的第一个单元格)的焦点。

请注意,此行为也管理RowPresenter中虚拟项目的实现,因此禁用它可能会导致不需要的GUI副作用。

您可以将您的容器GridIsHitTestVisible属性设置为false,这将禁用自动行选择行为。但显然,您无法处理行内细节内的任何点击。

+0

大答案,可怕的事实,所以我可以留下检查如果点击来自行的细节,如果是的话,保存现有的选定项目/索引,一旦控件已经完成了它们的自然行为重新应用选择......或者那里 – Hank

相关问题