【问题标题】:Manipulation event and panning mode操作事件和平移模式
【发布时间】:2013-02-19 09:26:48
【问题描述】:
我正在为支持触控的设备开发 WPF。我面临一个奇怪的问题。我的 XAML 结构是
<ScrollViewer>
<StackPanel orientation="Horizontal">
<!-- Control goes here -->
</StackPanel>
<ScrollViewer>
现在
-
要启用触摸滚动,我必须将 PannigMode 设置为 HorizontalOnly
-
要接收操作事件,我必须将 PannigMode 设置为 None
问题是我必须同时拥有这两个功能。
是否有任何解决方法可以使 scrollviewer 在触摸时滚动 并且触发 manipulationcompleted 事件。
请帮忙。
【问题讨论】:
标签:
c#
wpf
silverlight
xaml
scrollview
【解决方案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;
}
}
}