2

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

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

现在

  1. 要启用触摸滚动,我必须将 PannigMode 设置为Horizo ​​ntalOnly
  2. 要接收操作事件,我必须将PannigMode设置为None

问题是我必须同时拥有这两个功能。

是否有任何解决方法可以使滚动查看器在触摸时滚动并且触发操作完成事件。

请帮忙。

4

1 回答 1

1

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

  • 使用 MS Surface 工具包
  • 修复 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;
      }
   }
}
于 2013-09-04T09:20:57.407 回答