Pergunta

É possível alterar a quantidade que os pergaminhos WPF ScrollViewer? Estou simplesmente querendo saber se é possível mudar a scrollviewer de modo que quando usando a roda do mouse ou as setas ScrollViewer, a quantidade de rolagem incremental pode ser alterado.

Foi útil?

Solução

A resposta curta é:. Não há nenhuma maneira de fazer isso sem escrever algum costume rolagem código, mas não deixe que isso te assustar não é tão difícil

O ScrollViewer quer obras de rolagem usando unidades físicas (por exemplo pixels) ou por se envolver com uma implementação IScrollInfo usar unidades lógicas. Isto é controlado pela configuração a propriedade CanContentScroll , onde um valor de false significa "rolar o conteúdo utilizando unidades físicas" e um valor de verdadeiros meios "rolar o conteúdo logicamente".

Assim como o ScrollViewer rolar o conteúdo logicamente? Ao comunicar com uma aplicação IScrollInfo. Então é assim que você poderia assumir exatamente o quanto o conteúdo de seus pergaminhos do painel quando alguém executa uma ação lógica. Dê uma olhada na documentação para IScrollInfo para obter uma listagem de todas as unidades lógicas de measurment que podem ser solicitados a rolagem, mas desde que você mencionou a roda do mouse você estará mais interessado nos / métodos adequados MouseWheelUp / baixo / esquerda.

Outras dicas

Aqui está um simples, completa e trabalhando WPF classe ScrollViewer que tem uma propriedade SpeedFactor dados-bindable para ajustar a sensibilidade da roda do mouse. Definir SpeedFactor a 1,0 meios comportamento idêntico ao ScrollViewer WPF. O valor padrão para a propriedade de dependência é 2,5 , que permite a rolagem roda muito rápida.

É claro, você também pode criar recursos adicionais úteis, ligando-se ao próprio imóvel SpeedFactor, ou seja, para facilmente permitir que o usuário controle o multiplicador.

public class WheelSpeedScrollViewer : ScrollViewer
{
    public static readonly DependencyProperty SpeedFactorProperty =
        DependencyProperty.Register(nameof(SpeedFactor),
                                    typeof(Double),
                                    typeof(WheelSpeedScrollViewer),
                                    new PropertyMetadata(2.5));

    public Double SpeedFactor
    {
        get { return (Double)GetValue(SpeedFactorProperty); }
        set { SetValue(SpeedFactorProperty, value); }
    }

    protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
    {
        if (!e.Handled && 
            ScrollInfo is ScrollContentPresenter scp &&
            ComputedVerticalScrollBarVisibility == Visibility.Visible)
        {
            scp.SetVerticalOffset(VerticalOffset - e.Delta * SpeedFactor);
            e.Handled = true;
        }
    }
};

completa XAML demo de 'roda rápido rolagem do mouse' de cerca de 3200 itens de dados:

<UserControl x:Class="RemoveDuplicateTextLines.FastScrollDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyApp"
    xmlns:sys="clr-namespace:System;assembly=mscorlib">

    <local:WheelSpeedScrollViewer VerticalScrollBarVisibility="Auto">
        <ListBox ItemsSource="{Binding Source={x:Type sys:Object},Path=Assembly.DefinedTypes}" />
    </local:WheelSpeedScrollViewer>

</UserControl>

roda rápido mouse:

enter descrição da imagem aqui

Você poderia implementar um comportamento na scrollviewer. No meu caso CanContentScroll não funcionou. A solução abaixo funciona para rolagem com a roda do mouse, bem como arrastando a barra de rolagem.

public class StepSizeBehavior : Behavior<ScrollViewer>
{
    public int StepSize { get; set; }

    #region Attach & Detach
    protected override void OnAttached()
    {
        CheckHeightModulesStepSize();
        AssociatedObject.ScrollChanged += AssociatedObject_ScrollChanged;
        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.ScrollChanged -= AssociatedObject_ScrollChanged;
        base.OnDetaching();
    }
    #endregion

    [Conditional("DEBUG")]
    private void CheckHeightModulesStepSize()
    {
        var height = AssociatedObject.Height;
        var remainder = height%StepSize;
        if (remainder > 0)
        {
            throw new ArgumentException($"{nameof(StepSize)} should be set to a value by which the height van be divised without a remainder.");
        }
    }

    private void AssociatedObject_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        const double stepSize = 62;
        var scrollViewer = (ScrollViewer)sender;
        var steps = Math.Round(scrollViewer.VerticalOffset / stepSize, 0);
        var scrollPosition = steps * stepSize;
        if (scrollPosition >= scrollViewer.ScrollableHeight)
        {
            scrollViewer.ScrollToBottom();
            return;
        }
        scrollViewer.ScrollToVerticalOffset(scrollPosition);
    }
}

Você poderia usá-lo como este:

<ScrollViewer MaxHeight="248"
              VerticalScrollBarVisibility="Auto">
    <i:Interaction.Behaviors>
        <behaviors:StepSizeBehavior StepSize="62" />
    </i:Interaction.Behaviors>

Eu fiz isso para garantir números inteiros em scrollbar1.ValueChanged:

scrollbar1.Value = Math.Round(scrollbar1.Value, 0, MidpointRounding.AwayFromZero)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top