WPF DataGrid: можно ли горизонтальную прокрутку по столбцу, а не по пикселям (также как прокрутка содержимого)

В WPF DataGrid прокрутка по строкам встроена по умолчанию. То есть вы щелкаете стрелку вниз на вертикальной полосе прокрутки в DataGrid и прокручиваете вниз ровно на одну строку. Однако, если вы щелкните стрелку вправо на горизонтальной полосе прокрутки, вы не переместитесь вправо на один столбец - вы просто переместитесь вправо на фиксированное количество пикселей. Я хочу щелкнуть стрелку вправо и прокрутить вправо на один столбец. Точно так же, если пользователь щелкает и перетаскивает горизонтальную полосу прокрутки, я бы хотел, чтобы прокрутка прокручивалась только по столбцам, а не по пикселям.

Можно ли настроить WPF Datagrid так, чтобы горизонтальная прокрутка выполнялась по столбцам, а не по пикселям?

РЕДАКТИРОВАТЬ: Я также хотел бы, чтобы пользователь мог прокручивать по горизонтали, щелкая и перетаскивая большой палец, аналогично тому, как вертикальная прокрутка будет работать по строкам.


person skybluecodeflier    schedule 24.04.2015    source источник


Ответы (1)


Одним из решений было бы обработать событие ScrollViewer.ScrollChanged ...

<DataGrid x:Name="myGrid" ScrollViewer.ScrollChanged="dg_ScrollChanged"/>

и программно прокрутите до следующего смещения столбца, например:

    private void dg_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        if (e.HorizontalChange != 0) // horizontal scroll
        {
            if (e.OriginalSource is ScrollViewer)
            {
                // scoll to column offset
                ScrollViewer sv = e.OriginalSource as ScrollViewer;
                sv.ScrollToHorizontalOffset(GetColumnOffset(e.HorizontalChange > 0, sv.HorizontalOffset - e.HorizontalChange, sv.ScrollableWidth));
                e.Handled = true;
            }
        }
    }

Вам нужно будет написать метод GetColumnOffset. Вот быстрая и грязная реализация, которую я собрал. Вероятно, вы могли бы сделать его чище, и я не проводил тщательного тестирования, чтобы он мог содержать ошибки:

    private double GetColumnOffset(bool forward, double currentPos, double maxOffset)
    {
        ObservableCollection<DataGridColumn> Columns = myGrid.Columns;
        double columnPosition = 0;
        double maxColumnPosition = 0;
        double maxColumnIndex = 0;
        foreach (var column in Columns)
        {
            columnPosition += column.ActualWidth;
            if (columnPosition < maxOffset)
            {
                maxColumnPosition = columnPosition;
                maxColumnIndex = Columns.IndexOf(column);
            }
            if (forward && columnPosition > currentPos)
            {
                return columnPosition;
            }
        }

        if (!forward)
        {
            columnPosition = maxColumnPosition;
            if (maxColumnPosition < currentPos)
            {
                return maxColumnPosition;
            }
            foreach (var column in Columns.Reverse())
            {
                if (Columns.IndexOf(column) <= maxColumnIndex)
                {
                    columnPosition -= column.ActualWidth;
                    if (columnPosition < currentPos)
                    {
                        return columnPosition;
                    }
                }
            }
        }

        return 0;
    }
person Gordon True    schedule 24.04.2015
comment
Спасибо за ваш ответ. Этот базовый подход, похоже, работает для стрелок на обоих концах полосы прокрутки (мне пришлось внести ряд изменений в ваш код, чтобы заставить его работать). Однако, если пользователь перетаскивает полосу прокрутки, он быстро перемещается между двумя положениями. То есть при перетаскивании вызовы метода GetColumnOffset получают вперед == true, затем вперед == false, затем вперед == true и т. Д. Таким образом, колебания. - person skybluecodeflier; 27.04.2015
comment
Есть другие идеи? Я отредактировал свой вопрос, чтобы уточнить, что действительно хочу иметь возможность щелкать и перетаскивать большой палец. Извините, если было непонятно. - person skybluecodeflier; 27.04.2015