【问题标题】:Border in ControlTemplate causing odd selection behavior with DataGridControlTemplate 中的边框导致 DataGrid 出现奇怪的选择行为
【发布时间】:2009-07-01 14:03:01
【问题描述】:

我已将 Microsoft WPF DataGrid 中的 DataGridRow 重新模板化为以下内容,我遇到的问题是,如果用户单击模板的边框元素,则不会选择行。有没有办法让点击边框引起行选择。

<Grid x:Name="LayoutRoot" Margin="0,0,0,-1">
        <Border x:Name="DGR_Border" BorderBrush="Transparent" Background="Transparent" BorderThickness="1" CornerRadius="5" SnapsToDevicePixels="True">
            <Border x:Name="DGR_InnerBorder" BorderBrush="Transparent" Background="Transparent" BorderThickness="1" CornerRadius="5" SnapsToDevicePixels="True">
                <toolkit:SelectiveScrollingGrid Name="DGR_SelectiveScrollingGrid">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>

                    <Grid.RowDefinitions>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>

                    <toolkit:DataGridCellsPresenter Grid.Column="1" Name="DGR_CellsPresenter" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    <toolkit:DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" Visibility="{TemplateBinding DetailsVisibility}" toolkit:SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding RelativeSource={RelativeSource AncestorType={x:Type Controls:DataGrid}}, Path=AreRowDetailsFrozen, Converter={x:Static Controls:DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static Controls:SelectiveScrollingOrientation.Vertical}}" />
                    <toolkit:DataGridRowHeader Grid.RowSpan="2" toolkit:SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type Controls:DataGrid}}, Path=HeadersVisibility, Converter={x:Static Controls:DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static Controls:DataGridHeadersVisibility.Row}}"/>
                </toolkit:SelectiveScrollingGrid>
            </Border>
        </Border>
    </Grid>

【问题讨论】:

    标签: c# wpf xaml datagrid


    【解决方案1】:

    调用内部方法似乎有些危险。如果实施细节发生变化怎么办?以前的版本有很多变化。

    我认为将这样的事件处理程序简单地添加到您的行中可能更谨慎:

    protected void DataGridRow_MouseDown(object sender, MouseButtonEventArgs e)
    {
        // GetVisualChild<T> helper method, simple to implement
        DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
    
        // try to get the first cell in a row
        DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(0);
        if (cell != null)
        {
            RoutedEventArgs newEventArgs = new RoutedEventArgs(MouseLeftButtonDownEvent);
            //if the DataGridSelectionUnit is set to FullRow this will have the desired effect
            cell.RaiseEvent(newEventArgs);
        }
    }
    

    这与单击单元格本身的效果相同,并且仅使用 DataGrid 元素的公共成员。

    【讨论】:

      【解决方案2】:

      工具包 DataGridRow 没有定义 OnMouseDown 覆盖或类似方法。通过此方法处理整行的选择:

      internal void HandleSelectionForCellInput(DataGridCell cell, bool startDragging, bool allowsExtendSelect, bool allowsMinimalSelect)
      {
          DataGridSelectionUnit selectionUnit = SelectionUnit;
      
          // If the mode is None, then no selection will occur
          if (selectionUnit == DataGridSelectionUnit.FullRow)
          {
              // In FullRow mode, items are selected
              MakeFullRowSelection(cell.RowDataItem, allowsExtendSelect, allowsMinimalSelect);
          }
          else
          {
              // In the other modes, cells can be individually selected
              MakeCellSelection(new DataGridCellInfo(cell), allowsExtendSelect, allowsMinimalSelect);
          }
      
          if (startDragging)
          {
              BeginDragging();
          }
      }
      

      当输入发生在单元格上时调用此方法。 MakeFullRowSelection 方法只选择一行中的所有单元格,而不是行本身。

      因此,当您单击 DataGridRow(而不是 DataGridCell)时,不会发生鼠标按下或选择处理。要完成您想要的,您应该在您将设置 IsSelected 属性的行的鼠标按下事件中添加某种鼠标按下处理程序。当然,请注意,您应该为行中的每个单元格单独指定 selected 属性,因为 row.IsSelected 并不暗示或设置它。

      【讨论】:

        【解决方案3】:

        感谢您的回复,我明白了一般的想法,但是将 IsSelected 设置为 true 并没有按我预期的方式工作,当它命中时会导致该行被选中但不会取消选择另一行(在这种情况下它应该有)。我能够通过在我的处理程序中调用 HandleSelectionForCellInput 来解决这个问题。然后我只需调用从下面创建的 Lambda 与网格和单元格,就可以完美地工作。

        public static Action<DataGrid, DataGridCell, bool> CreateSelectRowMethod(bool allowExtendSelect, bool allowMinimalSelect)
        {
        var selectCellMethod = typeof(DataGrid).GetMethod("HandleSelectionForCellInput", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        
        ParameterExpression dataGrid = Expression.Parameter(typeof(DataGrid), "dataGrid");
        ParameterExpression paramCell = Expression.Parameter(typeof(DataGridCell), "cell");
        ParameterExpression paramStartDragging = Expression.Parameter(typeof(bool), "startDragging");
        var paramAllowsExtendSelect = Expression.Constant(allowExtendSelect, typeof(bool));
        var paramAllowsMinimalSelect = Expression.Constant(allowMinimalSelect, typeof(bool));
        
        var call = Expression.Call(dataGrid, selectCellMethod, paramCell, paramStartDragging, paramAllowsExtendSelect, paramAllowsMinimalSelect);
        
        return (Action<DataGrid, DataGridCell, bool>)Expression.Lambda(call, dataGrid, paramCell, paramStartDragging).Compile();
        }
        

        【讨论】:

          猜你喜欢
          • 2012-05-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多