Один из DataGrids не будет ScrollToCenterView - PullRequest
0 голосов
/ 10 апреля 2020

Я использую следующий класс для ScrollToCenterView для замены ScrollIntoView по умолчанию.

public static class ScrollToCenterView
{
    public static void ScrollToCenterOfView(this ItemsControl itemsControl, object item)
    {
        // Scroll immediately if possible
        if (!itemsControl.TryScrollToCenterOfView(item))
        {
            // Otherwise wait until everything is loaded, then scroll
            if (itemsControl is ListBox) ((ListBox)itemsControl).ScrollIntoView(item);
            itemsControl.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
            {
                itemsControl.TryScrollToCenterOfView(item);
            }));
        }
    }

    private static bool TryScrollToCenterOfView(this ItemsControl itemsControl, object item)
    {
        // Find the container
        if (!(itemsControl.ItemContainerGenerator.ContainerFromItem(item) is UIElement container)) return false;

        // Find the ScrollContentPresenter
        ScrollContentPresenter presenter = null;
        for (Visual vis = container; vis != null && vis != itemsControl; vis = VisualTreeHelper.GetParent(vis) as Visual)
            if ((presenter = vis as ScrollContentPresenter) != null)
                break;
        if (presenter == null) return false;

        // Find the IScrollInfo
        var scrollInfo =
            !presenter.CanContentScroll ? presenter :
            presenter.Content as IScrollInfo ??
            FirstVisualChild(presenter.Content as ItemsPresenter) as IScrollInfo ??
            presenter;

        // Compute the center point of the container relative to the scrollInfo
        System.Windows.Size size = container.RenderSize;
        System.Windows.Point center = container.TransformToAncestor((Visual)scrollInfo).Transform(new System.Windows.Point(size.Width / 2, size.Height / 2));
        center.Y += scrollInfo.VerticalOffset;
        center.X += scrollInfo.HorizontalOffset;

        // Adjust for logical scrolling
        if (scrollInfo is StackPanel || scrollInfo is VirtualizingStackPanel)
        {
            double logicalCenter = itemsControl.ItemContainerGenerator.IndexFromContainer(container) + 0.5;
            Orientation orientation = scrollInfo is StackPanel ? ((StackPanel)scrollInfo).Orientation : ((VirtualizingStackPanel)scrollInfo).Orientation;
            if (orientation == Orientation.Horizontal)
                center.X = logicalCenter;
            else
                center.Y = logicalCenter;
        }

        // Scroll the center of the container to the center of the viewport
        if (scrollInfo.CanVerticallyScroll) scrollInfo.SetVerticalOffset(CenteringOffset(center.Y, scrollInfo.ViewportHeight, scrollInfo.ExtentHeight));
        //if (scrollInfo.CanHorizontallyScroll) scrollInfo.SetHorizontalOffset(CenteringOffset(center.X, scrollInfo.ViewportWidth, scrollInfo.ExtentWidth));
        return true;
    }

    private static double CenteringOffset(double center, double viewport, double extent)
    {
        return Math.Min(extent - viewport, Math.Max(0, center - viewport / 2));
    }
    private static DependencyObject FirstVisualChild(Visual visual)
    {
        if (visual == null) return null;
        if (VisualTreeHelper.GetChildrenCount(visual) == 0) return null;
        return VisualTreeHelper.GetChild(visual, 0);
    }
}

Когда я запускаю событие, DataGrid 2 будет корректно отображать ScrollToCenterView, а DataGrid 1 вообще не будет прокручиваться. Код обеих DataGrids в точности одинаков, за исключением DataGrid 2, включающей группу:

mycollection.GroupDescriptions.Clear();
mycollection.GroupDescriptions.Add(new PropertyGroupDescription("PART"));
datagrid_parts.ItemsSource = mycollection.View;

Может кто-нибудь объяснить мне, почему DataGrid без группировки не прокручивается? Если я запускаю ScrollIntoView до ScrollToCenterView, то DataGrid 1 будет прокручиваться, как и предполагалось:

public void AddressesScrollIntoView()
{
    if (datagrid_addresses.SelectedIndex >= 0)
    {
        datagrid_addresses.ScrollIntoView(datagrid_addresses.Items[datagrid_addresses.SelectedIndex]);
        datagrid_addresses.ScrollToCenterOfView(datagrid_addresses.Items[datagrid_addresses.SelectedIndex]);
    }
}

Примечание : если я использую ScrollIntoView по умолчанию для DataGrid 2, мне нужно запустить UpdateLayout ( ) для правильной работы (это связано с группировкой), например: ({ ссылка }):

public void PartsScrollIntoView()
{
    if (datagrid_parts.SelectedIndex >= 0)
    {
        datagrid_parts.UpdateLayout();
        datagrid_parts.ScrollToCenterOfView(datagrid_parts.Items[datagrid_parts.SelectedIndex]);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...