2011-12-03 32 views
6

を働いていない私は、次のXAMLを持っている:スライダー ScrollViewerのは、WPFで適切

<ScrollViewer Canvas.Left="2266" Canvas.Top="428" Height="378" Name="scrollViewer1" Width="728" PanningMode="VerticalOnly" PanningRatio="2"> 
    <Canvas Height="1732.593" Width="507.667"> 
     <Slider Height="40.668" x:Name="slider1" Width="507.667" Style="{DynamicResource SliderStyle1}" Canvas.Left="15" Canvas.Top="150" /> 
     </Slider> 
    </Canvas> 
</ScrollViewer> 

それはスライダーを含むScrollViewerのです。私はタッチスクリーン上で次のものを使用しています。私はパンを使ってScrollViewerを垂直方向にスクロールしています。 PanningMode = "VerticalOnly"が設定されていると、スライダの動作が停止します。

私はScollViewerがタッチ\スライドイベントを消費し、スライダーがする前にそれを処理していると仮定している(しかし、私は、私はこの前に間違っていると思います)。

これに対応する方法はありますか?

答えて

10

私は、我々のアプリでこの問題を解決しました。

ScrollViewerは、TouchDeviceを他のコントロールから「盗む」PreviewTouchMoveハンドラでTouchDeviceをキャプチャし、PreviewTouchMoveイベントやTouchMoveイベントを受け取らないようにします。

この問題を回避するには、PreviewTouchDownイベントでTouchDeviceをキャプチャし、PreviewTouchUpイベントが発生するまでその参照を保存するカスタムThumbコントロールを実装する必要があります。その後、必要に応じて、コントロールはLostTouchCaptureハンドラでキャプチャを「盗む」ことができます。ここではいくつかの簡単なコードは次のとおりです。

public class CustomThumb : Thumb 
{ 
    private TouchDevice currentDevice = null; 

    protected override void OnPreviewTouchDown(TouchEventArgs e) 
    { 
     // Release any previous capture 
     ReleaseCurrentDevice(); 
     // Capture the new touch 
     CaptureCurrentDevice(e); 
    } 

    protected override void OnPreviewTouchUp(TouchEventArgs e) 
    { 
     ReleaseCurrentDevice(); 
    } 

    protected override void OnLostTouchCapture(TouchEventArgs e) 
    { 
     // Only re-capture if the reference is not null 
     // This way we avoid re-capturing after calling ReleaseCurrentDevice() 
     if (currentDevice != null) 
     { 
      CaptureCurrentDevice(e); 
     } 
    } 

    private void ReleaseCurrentDevice() 
    { 
     if (currentDevice != null) 
     { 
      // Set the reference to null so that we don't re-capture in the OnLostTouchCapture() method 
      var temp = currentDevice; 
      currentDevice = null; 
      ReleaseTouchCapture(temp); 
     } 
    } 

    private void CaptureCurrentDevice(TouchEventArgs e) 
    { 
     bool gotTouch = CaptureTouch(e.TouchDevice); 
     if (gotTouch) 
     { 
      currentDevice = e.TouchDevice; 
     } 
    } 
} 

次にあなたがCustomThumbの代わりに、デフォルトの親指のコントロールを使用するためにスライダーを再テンプレートする必要があります。

+2

私はまだこのアプローチをテストしていませんが、十分に有効です。私は答えとしてそれを選ぶでしょう。すべての問題を解決する方法は、Microsoft Surface 2.0 SDKのhttp://www.microsoft.com/download/en/details.aspx?id=26716を使用して、ScrollViewerをライブラリから使用することでした(上のすべての問題を処理します) )。 – Bassem

+1

この解決策は私のために働いた。タッチするのに適したシェイプ/サイズのカスタムThumbを使用するためにスライダを既に再テンプレートしていたので、非常に便利でした。 – tgr42

+0

提供されたアプローチは魅力のように機能します!私は(私の非難された)Microsoft Surface 2.0 SDKを削除する際に問題に直面しました。 – SSchuette

2

私は同様の問題で発作しました。回避策はこれでした(他のどれも私のために働いていませんでした):私はカスタムサムを作成し、次にそれをPART_Trackの親指としてxamlのスクロールバースタイル内で使用しました。

public class DragableThumb : Thumb 
{ 
    double m_originalOffset; 
    double m_originalDistance; 
    int m_touchID; 

    /// <summary> 
    /// Get the parent scrollviewer, if any 
    /// </summary> 
    /// <returns>Scroll viewer or null</returns> 
    ScrollViewer GetScrollViewer() 
    { 
     if (TemplatedParent is ScrollBar && ((ScrollBar)TemplatedParent).TemplatedParent is ScrollViewer) 
     { 
      return ((ScrollViewer)((ScrollBar)TemplatedParent).TemplatedParent); 
     } 

     return null; 
    } 

    /// <summary> 
    /// Begin thumb drag 
    /// </summary> 
    /// <param name="e">Event arguments</param> 
    protected override void OnTouchDown(TouchEventArgs e) 
    { 
     ScrollViewer scrollViewer; 

     base.OnTouchDown(e); 

     m_touchID = e.TouchDevice.Id; 

     if ((scrollViewer = GetScrollViewer()) != null) 
     { 
      m_originalOffset = scrollViewer.HorizontalOffset; 
      m_originalDistance = e.GetTouchPoint(scrollViewer).Position.X; 
     } 
    } 

    /// <summary> 
    /// Handle thumb delta 
    /// </summary> 
    /// <param name="e">Event arguments</param> 
    protected override void OnTouchMove(TouchEventArgs e) 
    { 
     ScrollViewer scrollViewer; 
     double actualDistance; 

     base.OnTouchMove(e); 

     if ((scrollViewer = GetScrollViewer()) != null && m_touchID == e.TouchDevice.Id) 
     { 
      actualDistance = e.GetTouchPoint(scrollViewer).Position.X; 
      scrollViewer.ScrollToHorizontalOffset(m_originalOffset + (actualDistance - m_originalDistance) * scrollViewer.ExtentWidth/scrollViewer.ActualWidth); 
     } 
    } 
} 
+0

ありがとう、これは私の問題の正しい軌道に私を設定します。 –

0

以下は私にとって役立ちました。私は何かするために長い間周りを検索しました。タッチのためにこれをHow to make WPF Slider Thumb follow cursor from any pointから変更しました。これははるかに簡単な修正であり、カスタムのスライダ/サムコントロールの作成を避けることができます。

これが機能するには、IsMoveToPointEnableをtrueに設定する必要があります。

private void Slider_OnTouchMove(object sender, TouchEventArgs e) 
{ 
    Slider slider = (Slider)sender;   
    TouchPoint point = e.GetTouchPoint (slider); 
    double d = 1.0/slider.ActualWidth * point.Position.X; 
    int p = int(slider.Maximum * d); 
    slider.Value = p; 
} 
0

これは素晴らしく、簡単で、私のために働いた - それは一般的な機能にまでラップし、それがゼロではないかもしれないとしても、スライダの最小値を処理するために拡張価値があるが。しかし、何をしなければならない苦痛。クールなWPFについては多くのことがありますが、非常に多くの簡単なことは、実際に生産性に有害な可能性がある余分なステップを必要とします。

関連する問題