1

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

我的应用程序旨在成为“记分表”......其中一个 PivotItems 具有 ScrollViewer(水平滚动,垂直禁用),内部有一个水平方向的 StackPanel。这个 StackPanel 包含一个“ScoreSheet”用户控件,它基本上是一个带有各种文本框的网格。所以......有点像这样(除了 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>

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

这一切都很好。:)

但是...问题出在 ScoreSheet 控件上,我想要一些按钮和文本框,以便用户可以在网格中输入分数。通过在 ScrollViewer 上设置“IsHitTestVisible”,点击/等。只是被忽略。

I tried setting "IsHitTestVisible" to "True" and instead running a function on the ScrollViewer's ManipulationStarted event (calling "e.Complete()")... but although that lets me access controls inside the ScoreSheet, I can't swipe left/right between PivotItems anymore.

So… can anyone help? I was thinking maybe I could refine the ManipulationStarted behavior somehow, maybe "passing along" the action to the Pivot control instead of having the ScrollViewer move? Or some other way I can make the ScrollViewer "inactive" but allow the controls within to be interactive?

I'd really appreciate any help. Thanks for your time!

4

2 回答 2

0

Firstly, I would say that your intended usage of the scrollviewer breaks the intended design of the scrollviewer and the pivot (a common mistake windows phone developers, including myself, have made). The main reason this is generally considered a bad practice is that it implements a side ways navigation paradigm that is intended to only be provided by the Pivot control and the Panorama control.

With that said, it doesn't mean your particular use is 100% bad, I think that there are times when breaking the rules is okay. I would just encourage you to do some research and really make sure you're not going to confuse the user, or force them to learn a navigation paradigm that they are not already familiar with through the phone's operating system, and apps that properly make use of the controls provided by the SDK.

Okay, so now that's out of the way, if you determine this really is the best design for your app, you'll need to do the following to accomplish what you want:

Instead of Using a Horizontal ScrollViewer, use a Pivot control inside your Pivot control

You'll need create a header template that is essentially empty so that you don't take up any space in the upper area of inner scrolling section.

This also makes a lot more sense because the horizontal scrolling you are trying to accomplish is by "section" instead of a continuous scroll. This saves you the trouble of having to think about exactly how many pixels you are scrolling (instead you can just use XAML to change the width of your PivotItems

Disable the scrolling functionality of the pivot scroll by the user

This can be done a number of different ways of varying complexity, and almost warrants a question on it's own. See here for one way to accomplish this.

Another thing to do (which gives you more control) is to capture the ManipulationStarted, ManipulationDelta, and ManipulationCompleted events on the inner pivot item. if you detect the delta manipulation containing a horizontal component, then inside the method handler for the ManipulationDelta event, set e.Handled = true. To cancel the inner Pivot's ability to handle the horizontal scrolling. That will look something like the following:

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

As you will discover, this can provide some odd behavior. Ideally, you'll want to figure out what works best for your app, but typically you want to check for more than just != 0 on the X component, and allow the user some little bit of x, just incase they hit the control at a weird angle such that the X component has a value of 1.

Implementing the buttons to move to the right or the left:

This should be pretty simple, just make use of the Pivot.SelectedIndex property.

However, in most cases, this is a bad idea. Be REALLY sure you are a good exception to standard practice (preferably by giving your app to someone who has never used it but owns a windows phone, and see if they intuitively understand how to use your app.

于 2012-04-26T06:26:39.043 回答
0

Many thanks to Paul for his input and advice. A Pivot offered some extra flexibility, but still had similar issues to the ScrollViewer control when IsHitTestVisible="False" (in that buttons and other controls on the contained elements would become unusable). Also, aesthetically for this app, I found I preferred the multiple ScoreSheets being right next to each other when the Previous/Next buttons were pressed and they were animated to show the new sheet (as PivotItems, one would scroll out of view before the next scrolled into place).

After some more thought and experimentation, I achieved the desired effect like this:

<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>

The "Canvas.Clip" let me hide the ScoreSheets on either side of the currently visible one, and I could animate the Canvas.Left position of the StackPanel when the Previous/Next buttons were pressed.

By avoiding the ScrollViewer or Pivot, there were no events to handle/override, and the controls in the StackPanel could then be accessed as I intended.

'hopefully that might be of help to others. :)

于 2012-04-28T02:16:38.460 回答