我已经将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>
答案 0 :(得分:2)
调用内部方法似乎有些危险。如果实施细节改变怎么办?以前的版本有很多变化。
我认为简单地向您的行添加这样的事件处理程序可能更为谨慎:
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元素的公共成员。
答案 1 :(得分:1)
工具包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并不暗示或设置该属性。
答案 2 :(得分:0)
感谢您的回复,我得到了一般的想法,但是将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();
}