ScrollIntoView с вложенным ScrollViewer - PullRequest
2 голосов
/ 29 июля 2011

В моем приложении у меня есть Canvas, завернутый в ScrollViewer (Canvas больше, чем размер экрана). На этом холсте я разместил другие элементы управления. Один из элементов на холсте содержит виртуализированную сетку данных (с более чем 2000 строк ... так что прокрутка также включена). Теперь у меня есть функция, которая выбирает строку в DataGrid на основе некоторых значений элемента строки (срабатывает автоматически). Когда строка выбрана, я звоню

uxDataGrid.ScrollIntoView(uxDataGrid.SelectedItems[0]);

что отлично работает. На самом деле это рабочий путь к добру. Я хочу, чтобы элемент DataGrid был выбран, а затем DataGrid должен прокрутиться до правильной позиции. Но мой прокручиватель Canvas как-то отвечает на этот запрос и прокручивает его там.

Я уже пытался перехватить ScrollChangedEvent и установить флаг обработки. Но это не работает.

Qustions:

1) Как я могу ограничить эффект вызова ScrollIntoView для локального пользовательского элемента управления.

2) Если это невозможно, как я могу выполнить прокрутку самостоятельно? Мне нужно рассчитать вертикальное смещение для прокрутки, но, поскольку оно виртуализировано, я понятия не имею, как узнать высоту строки?

Есть предложения?

Я добавил быстрый пример, чтобы продемонстрировать основные настройки. При нажатии на одну из кнопок я хочу, чтобы прокручивалась только DataGrid, а не ScrollViewer, ограничивающий холст.

<Window x:Class="ScrollTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<DockPanel>
    <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
        <Button Click="Button1_Click">Scroll to 1</Button>
        <Button Click="Button100_Click">Scroll to 100</Button>
        <Button Click="Button200_Click">Scroll to 200</Button>
    </StackPanel>
    <ScrollViewer>
        <Canvas Width="5000" Height="5000">
            <DataGrid Name="uxDataGrid" ItemsSource="{Binding TestItems}" Width="500" Height="500"></DataGrid>
        </Canvas>
    </ScrollViewer>
</DockPanel>

public class TestItem
{
    public TestItem(int id)
    {
        Property1 = id.ToString();
        Property2 = "B";
    }
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public IList<TestItem> TestItems { get; set; }
    public MainWindow()
    {
        TestItems = new List<TestItem>();
        for ( int i = 0; i < 300; i++ )
        {
            TestItems.Add(new TestItem(i));
        }

        InitializeComponent();
        DataContext = this;
    }


    private void Button1_Click( object sender, RoutedEventArgs e )
    {
        uxDataGrid.ScrollIntoView( TestItems[0]);
    }
    private void Button100_Click( object sender, RoutedEventArgs e )
    {
        uxDataGrid.ScrollIntoView( TestItems[99] );
    }
    private void Button200_Click( object sender, RoutedEventArgs e )
    {
        uxDataGrid.ScrollIntoView( TestItems[199] );
    }
}

1 Ответ

5 голосов
/ 29 июля 2011

Хорошо ... после некоторого исследования я нашел правильное событие: оно называется RequestBringIntoViewEvent. При перехвате этого он работает как положено:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        ...
        uxDataGrid.AddHandler( RequestBringIntoViewEvent, new RoutedEventHandler( HandleRequestBringIntoViewEvent ) );
    }

    private static void HandleRequestBringIntoViewEvent( object sender, RoutedEventArgs e )
    {
        e.Handled = true;
    }
    ...
}
...