【发布时间】:2014-06-18 20:29:21
【问题描述】:
我有一个 Pivot,其中包含一个 WebBrowser 控件,该控件实际上占据了整个页面(当然来自 Pivot 标题)。
我想弄清楚如何使 WebBrowser 控件允许用户向左/向右滑动以激活 Pivot 控件。目前它只是向左/向右平移 WebBrowser 控件
这个可以吗?
谢谢
【问题讨论】:
标签: c# silverlight windows-phone-7
我有一个 Pivot,其中包含一个 WebBrowser 控件,该控件实际上占据了整个页面(当然来自 Pivot 标题)。
我想弄清楚如何使 WebBrowser 控件允许用户向左/向右滑动以激活 Pivot 控件。目前它只是向左/向右平移 WebBrowser 控件
这个可以吗?
谢谢
【问题讨论】:
标签: c# silverlight windows-phone-7
虽然我无法准确告诉您如何将滑动传递给枢轴,但我可以告诉您如何完成部分工作:如何在 WebBrowser 上捕捉/分析/禁用自定义手势。
如果我没记错的话,在 7.0 中:
现在,在我拥有的 7.5 中(也许在 7.1 上,我不知道),似乎 MS 正在努力解决一些 WebBrowser 操作问题 --- 我认为他们正在努力实现滚动/滑动完全由 .Net 层处理。他们编写了一个特殊的类 PanZoomContainer 并将它们注入到 WebBrowser 内部模板的 VisualTree 中。 WebBrowserInterop 大大丰富了许多用于事件通知的隧道。 WebBrowserInterop 挂钩到 PanZoomContainer 的 ManipulationEvents,然后将它们传递给本机层。此外,它侦听来自本机层的事件/命令,例如称为“ZoomAndScroll”或“ShowSIP” - 并将它们主要传递回 PanZoomContainer。这个想法很清楚吧?他们已将事件处理从完全内部重新连接为有点意大利面,但已经通过 PanZoomC 实现了传递。
现在,这对我/我们有什么好处?
它是 PanZoomContainer,它的 Mani-Events 被检查。 TileHost 现在不捕获它们。在这个版本的 WebBrowser 控件中,它的 VisualTree 由一些边框、网格、一个 PanZoomContainer 和一个 TileHost(渲染器)组成。类似这样:
WebBrowser
PanZoom
ContentPresenter
Border/Name="border" <- you want this one
TileHost
我跳过了一些边框和网格,它们大多与问题无关。现在,如果 PanZoomContainer 的 Mani-Events 被监听,让我们阻止它们!
使用 VisualTreeHelper,只需越深入地挖掘,直到找到 FrameworkElement.Name=="border"。这是包装 TileHost 的边框,它是占据控件 99% 空间的“渲染器”。请注意,有一个 ContentPresenter,因此您可能必须等到控件模板被实例化(即 Loaded/LayoutUpdated)。
一旦您将手放在该边界上,请将所有 Mani-Event 处理程序附加到它:开始、增量和完成。 PanZoom 是一个普通的 xaml/silverlight/.net/etc 控件,所以它实际上服从 e.Handled = true :) 现在,如果你想禁用 ie。垂直滚动,过滤 Translation.Y0 的 Delta 和 Completed 事件。如果您想禁用点击但保留滚动/平移 - 过滤 X==0&Y==0。
这是最简单的部分。
困难的部分是尝试过滤不同的 Start/Delta/Stop 并根据自己的喜好调整行为。
虽然它可能看起来非常漂亮和诱人,但这不会轻易为您带来任何真实/漂亮的结果。例如,我写了“如果你想禁用垂直滚动,那么设置一个过滤器'if y==0 then e.handled=true'”。伟大的?简单的?没有!
假设我们想要“禁用有弹性的水平平移”,同时保留“垂直滚动”。反之亦然,无论如何,这只是一个例子:
这是一个带有灵敏触摸屏的小型矩形设备。请在屏幕上进行垂直滑动/平移/拖动,以使生成的 X-compound 为零。如果你设置这样的过滤器,它几乎是不可能正确的。你的用户会想杀了你,因为你强迫他们重试垂直滚动五次或更多次,直到他们做出完美的垂直滑动。
当然你可以让它不 ==0,但要留一些小余量。好的。但是如果你把边距设置得太大,控件会捕捉到中间的离轴运动,也会产生一个很小的水平平移。在几次不幸的垂直滑动之后,总的水平平移可能会从那些小的剩余物累积起来,位移可能会引人注目。
但还有一些其他恶毒的副作用:
简单地说,您已经提交了 e.Handled=true。活动结束了。死的。死亡。如果您只是想让 WebBrowser 跳过例如水平滑动,以便外部(枢轴)控件注意到它们并处理......哎呀。活动结束了。早些时候,TileHost/PanZoomC 已经熄灭了事件,现在您自己完成了。听起来像个糟糕的笑话,嗯?
幸运的是:
.. 所以乐趣就这样开始了,甚至可能更进一步。
【讨论】:
这类似于将地图放入 Pivot - 此处讨论 - http://mine.tuxfamily.org/?p=111 - 已经在很多问题中提到 - https://stackoverflow.com/search?q=mine.tuxfamily.org
一般来说,建议似乎是基于可用性的:
顺便说一句,如果您只是将网络浏览器控件用于非常少量的静态 html(因此您根本不需要任何滚动),那么您可以从网络浏览器中删除 HitTesting。
【讨论】:
我不知道 WP7 Pivot,但是 Pivot 控件上是否有任何 Preview* 事件允许您处理触摸并将它们标记为已处理?
【讨论】:
调用以下方法并将您的参数作为 PivotControl x:name 和 WebBrowserControl x:name 传递给此方法。
这里 WebBrowserControl 被放置在第二个枢轴项中,即枢轴索引为 1,我试图向左或向右滑动并分别到达枢轴索引 2 或 1。
public static void SwipteLeftRight(Microsoft.Phone.Controls.Pivot pivotControl, Microsoft.Phone.Controls.WebBrowser webBrowserControl)
{
var gesListener = GestureService.GetGestureListener(webBrowserControl);
gesListener.Flick += ((sen, args) =>
{
if (args.Direction == System.Windows.Controls.Orientation.Horizontal)
{
if (args.HorizontalVelocity < 0)
{
if (((Microsoft.Phone.Controls.PivotItem)(pivotControl.SelectedItem)).Header.ToString().Trim() == "Pivot Item name")
{
pivotControl.SelectedIndex = 2; //Next Pivot item
}
}
else if (args.HorizontalVelocity > 0)
{
if ((Microsoft.Phone.Controls.PivotItem)(pivotControl.SelectedItem)).Header.ToString().Trim() == "Pivot Item name")
{
pivotControl.SelectedIndex = 0; // Previous Pivot Item
}
}
}
});
}
它对我有用。干杯
【讨论】: