操纵事件和平移模式

时间:2013-02-19 09:26:48

标签: c# wpf silverlight xaml scrollview

我正在为支持触控的设备开发WPF。我面临一个奇怪的问题。我的XAML结构是

 <ScrollViewer>
     <StackPanel orientation="Horizontal">
         <!--  Control goes here -->
      </StackPanel>
  <ScrollViewer>

现在

  1. 要启用滚动触摸,我必须将 PannigMode 设置为 Horizo​​ntalOnly
  2. 要接收操纵事件,我必须将 PannigMode 设置为
  3. 问题是我必须同时拥有这两个功能。

    是否有任何解决方法,以便滚动查看器滚动,并且 actionscompleted 事件也会触发。

    请帮忙。

1 个答案:

答案 0 :(得分:1)

我有同样的问题。你至少有两个选择

  • 使用MS Surface Toolkit
  • 修复ScrollViewer

我选择了第二个。只需创建一个自定义控件,继承自ScrollViewer,在Generic.xaml中,您只需要输入<ContentPresenter />,仅此而已。 真正的工作是在代码背后,但也没有那么复杂。我必须检查用户是否触摸了按钮或只是想滚动。诀窍是检查触摸点上的内容并打开/关闭平移模式。

以下是代码:

namespace Demo.Controls
{
   public class ScrollViewerWithTouch : ScrollViewer
   {
    private PanningMode panningMode;


    private bool panningModeSet;

      static ScrollViewerWithTouch()
      {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(ScrollViewerWithTouch), new FrameworkPropertyMetadata(typeof(ScrollViewerWithTouch)));
      }

      protected override void OnManipulationCompleted(ManipulationCompletedEventArgs e)
      {
         base.OnManipulationCompleted(e);

         // set it back
         this.PanningMode = this.panningMode;
      }

      protected override void OnManipulationStarted(ManipulationStartedEventArgs e)
      {
         // figure out what has the user touched
         var result = VisualTreeHelper.HitTest(this, e.ManipulationOrigin);
         if (result != null && result.VisualHit != null)
         {
            var hasButtonParent = this.HasButtonParent(result.VisualHit);

            // if user touched a button then turn off panning mode, let style bubble down, in other case let it scroll
            this.PanningMode = hasButtonParent ? PanningMode.None : this.panningMode;
         }
         base.OnManipulationStarted(e);
      }

      protected override void OnTouchDown(TouchEventArgs e)
      {
         // store panning mode or set it back to it's original state. OnManipulationCompleted does not do it every time, so we need to set it once more.
         if (this.panningModeSet == false)
         {
            this.panningMode = this.PanningMode;
            this.panningModeSet = true;
         }
         else
         {
            this.PanningMode = this.panningMode;
         }

         base.OnTouchDown(e);         
      }

      private bool HasButtonParent(DependencyObject obj)
      {
         var parent = VisualTreeHelper.GetParent(obj);

         if ((parent != null) && (parent is ButtonBase) == false)
         {
            return HasButtonParent(parent);
         }

         return parent != null;
      }
   }
}