2009-05-18 32 views
6

FlowDocumentReader'da ViewingMode = "Scroll" ile bir FlowDocument görüntülüyorum. Fareyi tekerleğimde kullanırsam, belge çok yavaş kaydırılır. Kaydırma adımını artırmak istiyorum.ViewMode Viewer, Kaydırmak İçin Ayarlandığında FlowDocumentReader'ın Kaydırma Artışını Ayarlama?

  1. Faremin Kaydırma ayarını Denetim Masasında değiştirmeyi denedim, ancak bunun bir etkisi yok. WPF'nin FlowDocumentScrollViewer için bu ayarı yok saydığını düşünüyorum.

  2. FlowDocument ve FlowDocumentReader'da bir Scroll olayı ekledim, ancak fare tekerleğini kullandığımda yanmıyor.

  3. Ben FlowDocumentReader üzerinde Yüklü olay ekledik, kaydırma izleyicinin şablondan ScrollBar ("PART_VerticalScrollBar") bulundu ve SmallChange & LargeChange özelliklerini ayarlanabilir, ScrollViewer torunuyum aldık. Bunun da bir etkisi yoktu.

Herhangi bir fikri olan var mı?

+0

Eğer cevabımda yaptığınız aralar standart hız için '/ 6' ile yapılmış olsaydı, başka bir soruya cevap verirken bunu yapmanın daha iyi bir yolunu farkettim. Bunun yerine SystemInformation.MouseWheelScrollLines/3 (Geçerli bilgisayar ayarları/varsayılan) ile çarpılırsa, kullanıcıların statik ayarlarına göre fare ayarlarına göre çalışması gerekir. – rmoore

cevap

19

Sohnee sugested gibi biz bir denetimin MouseWheel durumunda bu değişiklik yapabilirsiniz, ancak o zaman sadece bir spesifik durum için çözülebilir ediyorum ve FlowDocumentReader, erişmesini olurdu hangi usinging eğer MVVM gibi bir şey, sen yapmazsın. Bunun yerine, ScrollViewer ile herhangi bir öğeye ayarlayabileceğimiz ekli bir özellik oluşturabiliriz. Ekli mülkümüzü tanımlarken, gerçek değişikliklerin kaydırma hızına göre gerçekleştirileceği bir PropertyChanged geri çağrısı da isteyeceğiz. Ben de 1: 1, varsayılan olarak 1, benim için 1-10 gibi bir şey yapabildiğiniz gibi kullanacağım hız aralığı .1x ile 3x verdim.

public static double GetScrollSpeed(DependencyObject obj) 
{ 
    return (double)obj.GetValue(ScrollSpeedProperty); 
} 

public static void SetScrollSpeed(DependencyObject obj, double value) 
{ 
    obj.SetValue(ScrollSpeedProperty, value); 
} 

public static readonly DependencyProperty ScrollSpeedProperty = 
    DependencyProperty.RegisterAttached(
    "ScrollSpeed", 
    typeof(double), 
    typeof(ScrollHelper), 
    new FrameworkPropertyMetadata(
     1.0, 
     FrameworkPropertyMetadataOptions.Inherits & FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
     new PropertyChangedCallback(OnScrollSpeedChanged))); 

private static void OnScrollSpeedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
{ 
} 

Şimdi bizim Ekli Mülkiyet olduğunu biz OnScrollSpeedChanged biz PreviewMouseWheel olayı işleyebilir, bunu yapmak için, kaydırma işlemek gerekir. ScrollViewer'ın standart MouseWheel olayını ele almadan önce gerçekleşecek bir tünel oluşturma olayı olduğundan, PreviewMouseWheel'e kanca yapmak istiyoruz.

Şu anda, PreviewMouseWheel işleyicisi FlowDocumentReader'ı veya buna bağlı olduğumuz diğer bir şeyi alıyor, ancak ihtiyacımız olan şey ScrollViewer. Bir çok şey olabileceğinden dolayı: ListBox, FlowDocumentReader, WPF Toolkit Grid, ScrollViewer, vs, bunu yapmak için VisualTreeHelper kullanan kısa bir yöntem yapabiliriz. Gelmekte olan öğenin bir çeşit DependancyObject olacağının farkındayız, bu nedenle ScrollViewer'ı bulmak için bazı özyinelemeyi kullanabiliriz.

public static DependencyObject GetScrollViewer(DependencyObject o) 
{ 
    // Return the DependencyObject if it is a ScrollViewer 
    if (o is ScrollViewer) 
    { return o; } 

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++) 
    { 
     var child = VisualTreeHelper.GetChild(o, i); 

     var result = GetScrollViewer(child); 
     if (result == null) 
     { 
      continue; 
     } 
     else 
     { 
      return result; 
     } 
    } 

    return null; 
} 

private static void OnScrollSpeedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
{ 
    var host = o as UIElement; 
    host.PreviewMouseWheel += new MouseWheelEventHandler(OnPreviewMouseWheelScrolled); 
} 

Şimdi ScrollViwer nihayet kaydırma hızını değiştirebilir alabilirsiniz. ScrollSpeed ​​özelliğini, gönderilmekte olan DependancyObject'den almamız gerekecek. Ayrıca, öğe içinde bulunan ScrollViewer'ı almak için yardımcı yöntemimizi kullanabiliriz. Bu iki şeye sahip olduktan sonra, ScrollViewer'ın VerticalOffset'ini alabilir ve değiştirebiliriz. Fare tekerleğinin değiştirdiği miktar olan MouseWheelEventArgs.Delta'yı 6'ya bölerek yaklaşık olarak varsayılan kaydırma hızını elde ettim. Böylece, ScrollSpeed ​​değiştiricimiz ile çarpılırsa, yeni ofset değerini alabiliriz. Ardından, ScrollViewer'ın VerticalOffset'ini, ortaya çıkardığı ScrollToVerticalOffset yöntemini kullanarak ayarlayabiliriz.

private static void OnPreviewMouseWheelScrolled(object sender, MouseWheelEventArgs e) 
{ 
    DependencyObject scrollHost = sender as DependencyObject; 

    double scrollSpeed = (double)(scrollHost).GetValue(Demo.ScrollSpeedProperty); 

    ScrollViewer scrollViewer = GetScrollViewer(scrollHost) as ScrollViewer; 

    if (scrollViewer != null) 
    { 
     double offset = scrollViewer.VerticalOffset - (e.Delta * scrollSpeed/6); 
     if (offset < 0) 
     { 
      scrollViewer.ScrollToVerticalOffset(0); 
     } 
     else if (offset > scrollViewer.ExtentHeight) 
     { 
      scrollViewer.ScrollToVerticalOffset(scrollViewer.ExtentHeight); 
     } 
     else 
     { 
      scrollViewer.ScrollToVerticalOffset(offset); 
     } 

     e.Handled = true; 
    } 
    else 
    { 
     throw new NotSupportedException("ScrollSpeed Attached Property is not attached to an element containing a ScrollViewer."); 
    } 
} 

Şimdi bizim Ekli Mülkiyet kurmak olduğuna göre, bunu göstermek için basit bir kullanıcı arayüzü oluşturabilirsiniz. ScrollSpeed'in birden çok denetime nasıl etkileneceğini görebilmemiz için bir ListBox ve bir FlowDocumentReaders oluşturacağım.

<UniformGrid Columns="2"> 
    <DockPanel> 
     <Slider DockPanel.Dock="Top" 
      Minimum=".1" 
      Maximum="3" 
      SmallChange=".1" 
      Value="{Binding ElementName=uiListBox, Path=(ScrollHelper:Demo.ScrollSpeed)}" /> 
     <ListBox x:Name="uiListBox"> 
      <!-- Items --> 
     </ListBox> 
    </DockPanel> 
    <DockPanel> 
     <Slider DockPanel.Dock="Top" 
      Minimum=".1" 
      Maximum="3" 
      SmallChange=".1" 
      Value="{Binding ElementName=uiListBox, Path=(ScrollHelper:Demo.ScrollSpeed)}" /> 
     <FlowDocumentReader x:Name="uiReader" 
      ViewingMode="Scroll"> 
      <!-- Flow Document Content --> 
     </FlowDocumentReader> 
    </DockPanel> 
</UniformGrid> 

Şimdi, koşarken, her bir sütundaki kaydırma hızını değiştirmek için Kaydırıcıları kullanabiliriz, eğlenceli şeyler.

+1

Harika! MVVM'ye benzer bir şey kullanıyorum ve yaklaşımınız mükemmel bir şekilde çalışacaktır. Bunu uygulamak için sabırsızlanıyorum. Thanx! – Christo

+1

Parlak çalışıyor! Sadece derlenip çalışmasını sağlamak için biraz düzeltmem gerekiyordu. – Christo

0

Kaydırma olayını kullanmak yerine, MouseWheel olayını yakalayın.

<FlowDocumentReader MouseWheel="..."> 
+0

Bunu deneyeceğim, belki işe yarar bir şey bulabilirim. Çok fazla kod yazmak zorunda kalmadan bunun çok zor olacağı fikrine çok fazla istifa ettim. – Christo

İlgili konular