none
ScrollViewer 触摸模式下滑动手指, 应该处理什么消息呢? RRS feed

  • 问题

  • 1. 我想在滑动手指的时候, 让后台去获得下一页的数据, 可是不知道该用什么消息, PointerWheelChanged和ViewChanged这两个消息我都没有收到。。。。

    2, 在Grid的ItemsControl里我添加了Tapped消息处理, 怎么知道我点击的时第几个item呢?

    代码如下:

    <Page
        x:Class="csharTest1.MainPage"
        IsTabStop="false"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:csharTest1"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.Resources>
            <ItemsPanelTemplate x:Key="detailItemsPanelTemplate">
                <WrapGrid Orientation="Horizontal" Margin="0,0,0,0" MaximumRowsOrColumns="2"/>
            </ItemsPanelTemplate>
            <DataTemplate x:Key="detailDataTemplate">
                <Border Width="760" Height="40" Background="Transparent" Margin="0">
                    <Grid>
                        <TextBlock Text="{Binding Title}" HorizontalAlignment="Left" FontSize="24"
                                   Margin="30, 5, 0, 0" Foreground="Black" TextTrimming="WordEllipsis" />
                    </Grid>
                </Border>
            </DataTemplate>
        </Page.Resources>
      
        <Grid Background="White">
           
            <ScrollViewer x:Name="scrollView" VerticalScrollBarVisibility="Hidden" VerticalScrollMode="Disabled" IsHitTestVisible="True"
                           PointerWheelChanged="ScrollViewer_PointerWheelChanged_1" ViewChanged="ScrollViewer_ViewChanged_1">
                <Grid>
                    <Rectangle Fill="#60000000" Margin="0, 0, 0, 0" Width="800" Height="500" RadiusX="5" RadiusY="5"/>
                    <Grid x:Name="detailGrid" Margin="300,150,0,0">
                        <ItemsControl Name="detail" ItemsSource="{Binding}"
                            ItemTemplate="{StaticResource detailDataTemplate}" 
                            ItemsPanel="{StaticResource detailItemsPanelTemplate}" 
                            Tapped="detail_Tapped_1">
                        </ItemsControl>
                    </Grid>
                </Grid>
            </ScrollViewer>
            
        </Grid>
    </Page>

    2012年8月20日 6:28

答案

  • 你在 PointerPressed中 可以让当前元素捕获Pointer 这样就不会因为Pointer移到其他控件上抬起而触发了其他控件的PointerReleased 且被处理掉。

            private void mediaElement_PointerPressed(object sender, PointerRoutedEventArgs e)
            {
                (sender as UIElement).CapturePointer(e.Pointer);
                startPosition = e.GetCurrentPoint(sender as UIElement).Position;  // 获得当前Pointer的位置
            }

    然后你在PointerReleased别忘了

    ReleasePointerCapture(e.Pointer);


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us


    2012年8月21日 8:23
    版主
  • ItemsControl 里面有一个ScrollViewer 他会处理掉你的PointerReleased 你如果面对这样的设计 ,其实你完全 只需要用ItemsControl里面的ScrollViewer就可以了, 设置 ItemsControl 的 ScrollViewer.XXXXXX 属性就可以开启他的支持滚动和显滚动条。

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年8月25日 15:34
    版主

全部回复

  • 1, 单指下滑,根据你在PointerPressed 和 PointerReleased 两个事件中获得的起始位置和终止位置计算位置差判断得到。

    2, 建议你还是用ListBox 或者 ListView这类已经实现具体ItemContainer的ItemsControl,否则我们难以判断点击的Item的ItemContainer类型。 如果你换了ListView ,则下面代码可以Work:

            private void detail_Tapped_1(object sender, TappedRoutedEventArgs e)
            {
                foreach (UIElement element in VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(sender as UIElement), sender as UIElement))
                {
                    if (element is ListViewItem)
                    {
                       var index = listview.ItemContainerGenerator.IndexFromContainer(element as ListViewItem);
                       break;
                    }
                }
            }


    否则, ItemsControl就多绕一个弯:

            private void detail_Tapped_1(object sender, TappedRoutedEventArgs e)
            {
                foreach (UIElement element in VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(sender as UIElement), sender as UIElement))
                {
                    if (element is Border && (element as Border).Name == "xxx")
                    {
                        var boundItem = (element as Border).DataContext;
                        var itemContainer = itemsControl.ItemContainerGenerator.ContainerFromItem(boundItem);
                        var index = itemsControl.ItemContainerGenerator.IndexFromContainer(itemContainer);
                        break;
                    }
                }
            }

    注意,你的DataTemplate中的Border需要有个名字,否则无法唯一判断是当前Item内的Border.

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年8月20日 10:48
    版主
  • PointerPressed 消息可以接收到, 可是PointerReleased 我接收不到,

    PointerRoutedEventArgs这个里面通过那个属性可以判断位置?
    2012年8月21日 5:27
  • 你在 PointerPressed中 可以让当前元素捕获Pointer 这样就不会因为Pointer移到其他控件上抬起而触发了其他控件的PointerReleased 且被处理掉。

            private void mediaElement_PointerPressed(object sender, PointerRoutedEventArgs e)
            {
                (sender as UIElement).CapturePointer(e.Pointer);
                startPosition = e.GetCurrentPoint(sender as UIElement).Position;  // 获得当前Pointer的位置
            }

    然后你在PointerReleased别忘了

    ReleasePointerCapture(e.Pointer);


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us


    2012年8月21日 8:23
    版主
  • 我试了下, 还是收不到PointerReleased消息, 哪里出错了呢?

    代码如下

    <Page
        x:Class="csharTest1.MainPage"
        IsTabStop="false"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:csharTest1"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.Resources>
            <ItemsPanelTemplate x:Key="detailItemsPanelTemplate">
                <WrapGrid Orientation="Horizontal" Margin="0,0,0,0" MaximumRowsOrColumns="2"/>
            </ItemsPanelTemplate>
            <DataTemplate x:Key="detailDataTemplate">
                <Border Width="760" Height="40" Background="Transparent" Margin="0">
                    <Grid>
                        <TextBlock Text="{Binding Title}" HorizontalAlignment="Left" FontSize="24"
                                   Margin="30, 5, 0, 0" Foreground="White" TextTrimming="WordEllipsis" />
                    </Grid>
                </Border>
            </DataTemplate>
        </Page.Resources>
        <Grid Background="Black">
            <ScrollViewer x:Name="scrollView" VerticalScrollBarVisibility="Hidden" VerticalScrollMode="Disabled" IsHitTestVisible="True"
                           PointerPressed="scrollView_PointerPressed_1" PointerReleased="scrollView_PointerReleased_1">
                <Grid>
                    <Rectangle Fill="#60FFFFFF" Margin="0, 0, 0, 0" Width="800" Height="500" RadiusX="5" RadiusY="5"/>
                    <Grid x:Name="detailGrid" Margin="300,150,0,0">
                        <ItemsControl Name="detail" ItemsSource="{Binding}"
                            ItemTemplate="{StaticResource detailDataTemplate}" 
                            ItemsPanel="{StaticResource detailItemsPanelTemplate}" 
                            >
                        </ItemsControl>
                    </Grid>
                    
                </Grid>
            </ScrollViewer>
        </Grid>
    </Page>

    namespace csharTest1
    {
        public class Item
        {
            public string Title { get; set; }
            public bool IsHighlighted { get; set; }
        }
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
                List<Item> items = new List<Item>();
                for (int i = 0; i < 10; i++)
                {
                    items.Add(new Item() { Title = "Item " + i, IsHighlighted = (i % 7 == 0 || i % 7 == 6) });
                }
                this.DataContext = items;
            }
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
            private void scrollView_PointerPressed_1(object sender, PointerRoutedEventArgs e)
            {
                (sender as UIElement).CapturePointer(e.Pointer);
                Point startPoint = e.GetCurrentPoint(sender as UIElement).Position;
            }
            private void scrollView_PointerReleased_1(object sender, PointerRoutedEventArgs e)
            {
                ReleasePointerCapture(e.Pointer); int a = 0;
            }
        }
    }

    2012年8月22日 1:59
  • 还没有找到答案~~~ 为什么呢?
    2012年8月24日 7:08
  • ItemsControl 里面有一个ScrollViewer 他会处理掉你的PointerReleased 你如果面对这样的设计 ,其实你完全 只需要用ItemsControl里面的ScrollViewer就可以了, 设置 ItemsControl 的 ScrollViewer.XXXXXX 属性就可以开启他的支持滚动和显滚动条。

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年8月25日 15:34
    版主
  • 谢谢,

    我做的类似行事历的页面, 当前月的内容正好显示在Grid的ItemsControl中, 所以不会出现滚动条,

    需要根据手滑动的方向, 来判断后台获取上个月还是下个月的内容,然后更新UI,

    一开始根据你的建议:

    1, 单指下滑,根据你在PointerPressed 和 PointerReleased 两个事件中获得的起始位置和终止位置计算位置差判断得到。

    但是现在PointerReleased 接受不到, 还有什么其他方法实现这个功能么?

    2012年8月27日 2:05
  • 我的意思是,你不需要外面的ScrollViewer了,因为 ItemsControl 他自己会带有 ScrollViewer, 本身如果内容益处的话可以显示滚动条。

    所以关于 PointerPressed 和 PointerReleased 两个事件,你可以直接在 ItemsControl上实现。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年8月28日 8:56
    版主
  • 唉。。。。。试了半天还是没解决~

    我是用Simulator上调试的, 在鼠标模式下面是可以收到PointerReleased消息的,

    可是我切换到Basic touch mode下的时候, 就收不到PointerReleased了

    2012年9月10日 3:42