WP7 / Silverlight:ScrollViewer中的非活动按钮,IsHitTestVisible = False ...在数据透视表内部

时间:2012-04-26 04:03:23

标签: silverlight windows-phone-7 xaml scrollviewer

我在我的应用程序上取得了一些进展,但遇到了一个让我难过的问题。我希望有人可以提供他们的专业知识吗?

我的应用程序旨在成为“记分表”...其中一个PivotItems具有ScrollViewer(水平滚动,垂直禁用),内部有水平方向StackPanel。这个StackPanel包含一个“ScoreSheet”UserControl,它基本上是一个带有各种文本框的网格。所以...有点像这样(除了ScoreSheet项目以编程方式添加到StackPanel):

<controls:PivotItem>
   <controls:PivotItem.Header>
      <TextBlock Text="score sheet" FontSize="45" Height="80" />
   </controls:PivotItem.Header>

   <ScrollViewer Width="470" Height="560" VerticalAlignment="Top" x:Name="sv_scoresheets" MaxHeight="560" MinHeight="560" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled" IsHitTestVisible="False">
      <StackPanel Name="sp_scoresheets" Orientation="Horizontal">
         <local:ScoreSheet></local:ScoreSheet>
         <local:ScoreSheet></local:ScoreSheet>
         <local:ScoreSheet></local:ScoreSheet>
      </StackPanel>
   </ScrollViewer>

</controls:PivotItem>

概念是“Previous”和“Next”按钮位于页面底部的ApplicationBar中,它们向左或向右触发ScrollViewer的动画(即当前Round * ScoreSheet的宽度)。通过在ScrollViewer上将“IsHitTestVisible”设置为“False”,用​​户无法手动将显示的ScoreSheet移动到奇怪的位置,并且在PivotItems之间向左/向右滑动仍然按预期工作。

这一切都很顺利。 :)

然而......问题在于ScoreSheet控件,我想要一些Buttons和TextBoxes,这样用户就可以在网格中输入一个分数。通过在ScrollViewer上使用“IsHitTestVisible”,点击/等。只是被忽略了。

我尝试将“IsHitTestVisible”设置为“True”,而是在ScrollViewer的ManipulationStarted事件上运行一个函数(调用“e.Complete()”)......但是虽然这样我可以访问ScoreSheet中的控件,但我可以' t再次在PivotItems之间向左/向右滑动。

所以...有人可以帮忙吗?我想也许我可以以某种方式改进ManipulationStarted行为,也许“将”传递给Pivot控件而不是让ScrollViewer移动?或者其他一些方法我可以让ScrollViewer“无效”但允许其中的控件是交互式的?

我真的很感激任何帮助。 谢谢你的时间!

2 个答案:

答案 0 :(得分:0)

首先,我要说滚动查看器的预期用途会破坏滚动查看器和枢轴的预期设计(包括我自己在内的Windows手机开发人员常犯的错误)。这通常被认为是一种不好的做法的主要原因是它实现了一种侧向导航范例,其目的是由Pivot控件和Panorama控件提供。

据说,这并不意味着你的特殊用途是100%坏,我认为有时候违反规则是可以的。我只是鼓励你做一些研究,并确保你不会混淆用户,或强迫他们通过手机的操作系统学习他们不熟悉的导航范例,以及正确使用的应用程序SDK提供的控件。

好的,现在已经不在了,如果你确定这确实是你的应用程序的最佳设计,你需要做以下事情来完成你想要的:

使用Pivot控件内的Pivot控件

而不是使用Horizo​​ntal ScrollViewer

您需要创建一个基本上为空的标题模板,这样您就不会占用内部滚动部分上方区域的任何空间。

这也更有意义,因为您尝试完成的水平滚动是通过“部分”而不是连续滚动。这样可以省去必须考虑滚动的像素数量的问题(相反,您只需使用XAML来更改数据透视图的宽度

禁用用户

的轴心滚动的滚动功能

这可以通过多种不同的方式来改变复杂性,并且几乎可以保证自己的问题。有关实现此目的的一种方法,请参阅here

要做的另一件事(让您获得更多控制权)是捕获内部枢轴项上的ManipulationStartedManipulationDeltaManipulationCompleted事件。 if 您检测到包含水平组件的delta操作,然后在ManipulationDelta事件的方法处理程序中设置e.Handled = true。取消内部Pivot处理水平滚动的能力。这将类似于以下内容:

// Event handler for ManipulationDelta event on your inner Pivot control
public void OnManipulationDelta(ManipulationDeltaEventArgs e)
{
    if(e.DeltaManipulation.Translation.X != 0)
        e.Handled = true;
}

正如您将发现的,这可能会提供一些奇怪的行为。理想情况下,您需要找出哪种方法最适合您的应用,但通常您要检查的不仅仅是X组件上的!= 0,并且允许用户使用一些x,只是因为它们会触及控件以奇怪的角度使X分量的值为1。

实施按钮向右或向左移动:

这应该非常简单,只需使用Pivot.SelectedIndex属性。

但是,在大多数案例中,这是一个坏主意。确实你是标准练习的一个很好的例外(最好是将你的应用程序提供给从未使用过但拥有Windows手机的人,看看他们是否直观地了解如何使用你的应用程序。

答案 1 :(得分:0)

非常感谢保罗的意见和建议。 Pivot提供了一些额外的灵活性,但当IsHitTestVisible =“False”时,ScrollViewer控件仍然存在类似问题(因为所包含元素上的按钮和其他控件将变得无法使用)。此外,在这个应用程序的美学上,我发现当按下上一个/下一个按钮时,我更喜欢多个ScoreSheets彼此相邻,并且它们被动画化以显示新的工作表(作为PivotItems,一个将在下一个之前滚动出视图滚动到位。)

经过一番思考和实验,我达到了预期的效果:

<Canvas Width="470" Height="560" VerticalAlignment="Top" MaxHeight="560" MinHeight="560" MinWidth="470" MaxWidth="470">
   <Canvas.Clip>
      <RectangleGeometry Rect="0,0,470,560" />
   </Canvas.Clip>
   <StackPanel Name="sp_scoresheets" Orientation="Horizontal" CacheMode="BitmapCache">
      <local:ScoreSheet /></local:ScoreSheet>
      <local:ScoreSheet /></local:ScoreSheet>
      <local:ScoreSheet /></local:ScoreSheet>
   </StackPanel>
</Canvas>

“Canvas.Clip”让我在当前可见的一侧隐藏ScoreSheets,当按下上一个/下一个按钮时,我可以为StackPanel的Canvas.Left位置设置动画。

通过避开ScrollViewer或Pivot,没有事件要处理/覆盖,然后可以按照我的意图访问StackPanel中的控件。

'希望这对其他人有帮助。 :)