WPF DataGrid: как я останавливаю автоматическую прокрутку, когда ячейка нажата?

Проблема:
Если мой DataGrid не совсем видимо (горизонтальные и вертикальные полосы прокрутки показывают), и я нажимаю на одну из своих ячеек, которая частично видима, автопрокрутки сетки для обеспечения той ячейки в представление. Я не хочу, чтобы это произошло. Я попытался играть вокруг с RequestBringIntoView, как это:

private void DataGrid_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
    e.Handled = true;
}

Но это ничего не делает.

Вещи я попробовал:

  • Мои ячейки являются пользовательскими UserControls; Я пытался поместить обработчик событий для RequestBringIntoView на всех UserControls это составляет мои ячейки и пыталось обработать событие, думая, что, возможно, я не делал достаточно, просто обработав RequestBringIntoView на DataGrid самостоятельно. Это не работало.
  • Размещенный DataGrid в a ScrollViewer, и обработанный ScrollViewer RequestBringIntoView событие. Это на самом деле работает и останавливает поведение автопрокрутки, но в моем случае, размещающем a DataGrid в a ScrollViewer нисколько не желательно, таким образом, я должен предложить другое решение.

Я не уверен, как остановить это поведение, какие-либо идеи?

26
задан Dave Clemmer 15 September 2011 в 18:40
поделиться

3 ответа

Вы можете получить доступ к внутренней ScrollViewer DataGrid, изменяя шаблон. Хотя обычно вы бы не поместите обработчик событий для кода в шаблоне, если вы объявляете встроенный шаблон, вы можете обрабатывать обработчик событий так же, как вы находитесь, когда вы прикрепляете его к самому DataGrid. Это шаблон по умолчанию, созданный из смешивания, включая добавленный обработчик на ScrollViewer для Event ProcessBriingIntoview:

<ControlTemplate TargetType="{x:Type Controls:DataGrid}">
<Border SnapsToDevicePixels="True" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
    <ScrollViewer x:Name="DG_ScrollViewer" Focusable="False" RequestBringIntoView="DG_ScrollViewer_RequestBringIntoView">
        <ScrollViewer.Template>
            <ControlTemplate TargetType="{x:Type ScrollViewer}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Button Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type Controls:DataGrid}}}" Focusable="False">
                        <Button.Visibility>
                            <Binding Path="HeadersVisibility" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type Controls:DataGrid}}">
                                <Binding.ConverterParameter>
                                    <Controls:DataGridHeadersVisibility>All</Controls:DataGridHeadersVisibility>
                                </Binding.ConverterParameter>
                            </Binding>
                        </Button.Visibility>
                        <Button.Template>
                            <ControlTemplate TargetType="{x:Type Button}">
                                <Grid>
                                    <Rectangle x:Name="Border" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" SnapsToDevicePixels="True"/>
                                    <Polygon x:Name="Arrow" Fill="Black" Stretch="Uniform" HorizontalAlignment="Right" Margin="8,8,3,3" VerticalAlignment="Bottom" Opacity="0.15" Points="0,10 10,10 10,0"/>
                                </Grid>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsMouseOver" Value="True">
                                        <Setter Property="Stroke" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
                                    </Trigger>
                                    <Trigger Property="IsPressed" Value="True">
                                        <Setter Property="Fill" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
                                    </Trigger>
                                    <Trigger Property="IsEnabled" Value="False">
                                        <Setter Property="Visibility" TargetName="Arrow" Value="Collapsed"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Button.Template>
                        <Button.Command>
                            <RoutedCommand/>
                        </Button.Command>
                    </Button>
                    <Custom:DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.Column="1">
                        <Custom:DataGridColumnHeadersPresenter.Visibility>
                            <Binding Path="HeadersVisibility" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type Controls:DataGrid}}">
                                <Binding.ConverterParameter>
                                    <Controls:DataGridHeadersVisibility>Column</Controls:DataGridHeadersVisibility>
                                </Binding.ConverterParameter>
                            </Binding>
                        </Custom:DataGridColumnHeadersPresenter.Visibility>
                    </Custom:DataGridColumnHeadersPresenter>
                    <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.ColumnSpan="2" Grid.Row="1" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False"/>
                    <ScrollBar x:Name="PART_VerticalScrollBar" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Grid.Column="2" Grid.Row="1" Maximum="{TemplateBinding ScrollableHeight}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}"/>
                    <Grid Grid.Column="1" Grid.Row="2">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type Controls:DataGrid}}}"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <ScrollBar x:Name="PART_HorizontalScrollBar" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Grid.Column="1" Maximum="{TemplateBinding ScrollableWidth}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}"/>
                    </Grid>
                </Grid>
            </ControlTemplate>
        </ScrollViewer.Template>
        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
    </ScrollViewer>
</Border>

7
ответ дан 28 November 2019 в 07:00
поделиться

Я не уверен, что это работает, но вот идея, основанная на некотором исследовании, выполнена в исходном коде данных DataGrid с использованием отражателя:

1 / Создание класса, которое наследует DataGridCellSpanel. Это панель, которая используется внутри DataGrid, чтобы организовать клетки

2 / переопределить метод ANNIDEXINTOVIVEW с помощью пустого метода (без вызова базового метода)

3 / Установите свойство PerficePaneltemplate в вашем XAML:

<tk:DataGrid>
    <tk:DataGrid.ItemsPanel>
        <ItemsPanelTemplate>
            <local:DataGridCellsPanelNoAutoScroll />
        </ItemsPanelTemplate>
    </tk:DataGrid.ItemsPanel>
</tk:DataGrid>

Кажется, что когда происходит событие Mousedown, в какой-то момент метод AndiDexIntoview на панели вызывается для выполнения автоматического прокрутки. Замена его без op может сделать трюк.

У меня не было времени, чтобы проверить это решение, пожалуйста, дайте нам знать, если он работает.

1
ответ дан 28 November 2019 в 07:00
поделиться

Я занял больше времени, чтобы взглянуть на эту проблему, так как мое первое решение не работало.

Однако ответ Джона почти хороший. Хитрость состоит в том, чтобы поймать событие PreloveBriNTOView, прежде чем он попадет в ScrollViewer, чтобы пометить его обрабатывалось.

Если вам не нужно усовершенствовать весь шаблон, вы можете использовать следующий код:

var scp = TreeHelper.FindVisualChild<ScrollContentPresenter>(this.datagrid);
scp.RequestBringIntoView += (s, e) => e.Handled = true;

Используем ScrollContentPresenter, потому что он чуть ниже ScrollViewer в визуальном дереве.

Надеюсь, это поможет!

9
ответ дан 28 November 2019 в 07:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: