Граница в ControlTemplate вызывает нечетное поведение выбора с DataGrid

2

Я обновил DataGridRow в Microsoft WPF DataGrid ниже, проблема, с которой я сталкиваюсь, - это если пользователь нажимает на элементы границы шаблона, строки (строки) не выбираются. Есть ли способ сделать клик на границе причиной выбора строки.

<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>
Теги:
xaml
wpf
datagrid

3 ответа

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.

  • 0
    Отлично работает, спасибо!
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. Разумеется, обратите внимание, что вы должны указывать выбранное свойство для каждой ячейки в строке по отдельности, так как строка .IsSelected не подразумевает или не устанавливает это.

0

Спасибо за ответ, я получил общую идею, однако установка IsSelected в true не работала так, как я ожидал, когда это ударит, это приведет к тому, что строка станет выбрана, но не отменит выбор другой строки (в случаях он должен иметь). Мне удалось обойти проблему, вызвав HandleSelectionForCellInput в моем обработчике. Затем я просто называю Лямбду, созданную снизу сеткой и ячейкой, прекрасно работает.

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();
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню