JP Garza
JP Garza

Reputation: 270

How can I prevent touch-click when touch-scrolling?

I have an ItemsControl that wraps its ItemPresenter with a ScrollViewer. That ItemPresenter displays a ListView. Therefore I have a collection within a collection.

Now, I want only the ScrollViewer to have scrolling functionality so I have gone ahead and removed the scrolling functionality from the inner ListView.

The problem is that my scrolling event is being messed up by the ListView. As soon as my finger touches the content area it selects the ListViewItems instead of scrolling.

How can I tell through routed events if the user is trying to click or scroll? and if it is scroll, how do I prevent it from selecting the ListViewItems?

<ItemsControl ItemsSource="{Binding Countries}" >
   <ItemsControl.Template>
      <ControlTemplate>
         <ScrollViewer PanningMode="VerticalOnly">
            <ItemsPresenter/>
         </ScrollViewer>
      </ControlTemplate>
   </ItemsControl.Template>

   <ItemsControl.ItemTemplate>
      <DataTemplate>
         <ListView ItemsSource="{Binding Cities}">
            <ListView.Template>
               <ControlTemplate>
                  <ItemsPresenter/>
               </ControlTemplate>
             </ListView.Template>
         </ListView>
      </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>

Upvotes: 2

Views: 335

Answers (1)

Shane Duffy
Shane Duffy

Reputation: 1147

There isn't any way to look into the future to see if a user is going to begin scrolling after touching the screen or simply lift their finger off immediately afterwards. A Future API would be nice, though.

Anyhow, you could just check to see if the user has moved their finger at all after touching the ListView. If so, begin treating the "touch" like a "scroll" rather than a "click" by manually scrolling the ScrollViewer and deselecting the ListView items.

Something like this:

private bool _touchDown = false;
private double _initOffset = 0;
private double _scrollDelta = 5;

private void ListView_PreviewTouchDown(object sender, TouchEventArgs e) 
{
    _touchDown = true;
    _initOffset = e.GetTouchPoint(this).Y;
}

private void ListView_PreviewTouchMove(object sender, TouchEventArgs e) 
{
    if (_touchDown && Math.Abs(r.GetTouchpoint(this).Y - _initOffset) > _scrollDelta) 
    {
        My_ScrollViewer.ScrollToVerticalOffset(r.GetTouchpoint(this).Y - _initOffset);
        My_ListView.UnselectAll();
    }
}

private void ListView_PreviewTouchUp(object sender, TouchEventArgs e) 
{
    _touchDown = false;
    _initOffset = 0;
}

Disclaimer: I just wrote this in notepad. It has problems, but it gets the concept across.

Upvotes: 1

Related Questions