【问题标题】:Pull To Refresh with Long List Selector Windows Phone 8使用长列表选择器拉取刷新 Windows Phone 8
【发布时间】:2013-11-30 06:53:59
【问题描述】:

我目前正在使用 Windows Phone 8 应用程序,但遇到了长列表选择器 (LLS) 的一些问题。 列表框通过使用 TranslateY 值来实现:

 UIElement scrollContent = (UIElement)this.targetScrollViewer.Content;
 CompositeTransform ct = scrollContent.RenderTransform as CompositeTransform;
 //ct.TranslateY: I need this value in Viewport's LLS to detect exactly the distance moving from the TOP

我正在尝试使用 LLS 检测下拉刷新,但它有一些缺陷(使用鼠标输入、移动和离开):

    double manipulationStart = 0;
    double manipulationEnd = 0;

    void targetLLS_MouseEnter(object sender, MouseEventArgs e)
    {
        if (!this.IsRefreshing)
        {
            var pos = e.GetPosition(null);
            manipulationStart = pos.Y;
            IsMoving = false;
        }
    }

    private void targetLLS_MouseMove(object sender, MouseEventArgs e)
    {
        if (!this.IsRefreshing)
        {
            var pos = e.GetPosition(null);

            manipulationEnd = pos.Y;
            IsMoving = true;

            double TranslateY = manipulationEnd - manipulationStart;

            if (TranslateY > this.PullThreshold)
            {
                this.PullDistance = 100;
                this.PullFraction = 1.0;
                activityState = PullDownToRefreshPanel.ReadyToReleaseVisualState;
            }
            else if (TranslateY > 0)
            {
                this.PullDistance = 100;
                double threshold = this.PullThreshold;
                this.PullFraction = 1;// threshold == 0.0 ? 1.0 : Math.Min(1.0, TranslateY / threshold);
                activityState = PullDownToRefreshPanel.PullingDownVisualState;
            }
            else
            {
                this.PullDistance = 0;
                this.PullFraction = 0;
                activityState = PullDownToRefreshPanel.InactiveVisualState;
            }

            VisualStateManager.GoToState(this, activityState, false);
        }
    }

    bool IsMoving = false;
    void targetLLS_MouseLeave(object sender, MouseEventArgs e)
    {
        if (!this.IsRefreshing && IsMoving)
        {
            double TranslateY = manipulationEnd - manipulationStart;
            EventHandler handler = this.RefreshRequested;

            if (this.targetLLS.IsAtTop()
                && (activityState == PullDownToRefreshPanel.ReadyToReleaseVisualState))// TranslateY >= this.PullThreshold
            {
                if (handler != null)
                {
                    IsRefreshing = true;
                    handler(this, EventArgs.Empty);
                }
            }

            IsMoving = false;
        }

        PullDistance = 0;
        PullFraction = 0;
        manipulationStart = 0;
        manipulationEnd = 0;
        activityState = PullDownToRefreshPanel.InactiveVisualState;
        //VisualStateManager.GoToState(this, activityState, false);
    }

如何使用以下模板:

 <Style x:Key="ViewportControlStyle" TargetType="ViewportControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ViewportControl">
                <ContentPresenter x:Name="ContentElement" Cursor="{TemplateBinding Cursor}" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="LongListSelectorNormalStyle" TargetType="phone:LongListSelector">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="phone:LongListSelector">
                <Grid Background="{TemplateBinding Background}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="ScrollStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition GeneratedDuration="00:00:00.5"/>
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="Scrolling">
                                <Storyboard>
                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VerticalScrollBar"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="NotScrolling"/>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Grid Margin="{TemplateBinding Padding}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <ViewportControl x:Name="ViewportControl" HorizontalContentAlignment="Stretch" VerticalAlignment="Top" Style="{StaticResource ViewportControlStyle}"/>
                        <ScrollBar x:Name="VerticalScrollBar" Grid.Column="0" Margin="4,0,4,0" Opacity="0" Orientation="Vertical" HorizontalAlignment="Right"/>
                    </Grid>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我的项目需要实现拉功能所以请帮助我。 感谢阅读!

【问题讨论】:

标签: c# xaml windows-phone-8 windows-phone


【解决方案1】:

您可以通过ItemRealized 事件并使用ListHeader(或ListFooter 从底部拉出)来完成此操作。在 ItemRealized 事件中,您检查该项目是否是您的标题对象。如果是则加载更多项目。

来自Windows Phone Dev Blog

每次 LongListSelector 项获取要在屏幕上显示的 UI 容器时都会引发 ItemRealized 事件。换句话说,每次项目进入当前视口上方或下方的 UI 缓冲区时,都会引发 ItemRealized 事件。事件参数属性 ItemKind 指示 UI 容器是 ItemListHeaderGroupHeader 还是 列表页脚。使用 Container.Content 属性,您可以获得与已实现的 UI 容器关联的实际对象。这样您就可以监控 UI 容器缓冲区中的对象。

请注意此示例中的应用代码如何包含私有变量 _offsetKnob。这有助于微调 LongListSelector 滚动体验,帮助确定何时加载更多项目,具体取决于项目模板的重量,或发送数据的服务的响应速度。

来自他们提供的Twitter sample

void resultList_ItemRealized(object sender, ItemRealizationEventArgs e)
{
    if (!_viewModel.IsLoading && resultList.ItemsSource != null && resultList.ItemsSource.Count >= _offsetKnob)
    {
        if (e.ItemKind == LongListSelectorItemKind.Item)
        {
            if ((e.Container.Content as TwitterSearchResult).Equals(resultList.ItemsSource[resultList.ItemsSource.Count - _offsetKnob]))
            {
                _viewModel.LoadPage(_searchTerm, _pageNumber++);
            }
        }
    }
}

下载完整的Twitter Search sample

【讨论】:

    【解决方案2】:

    这并不完全是微不足道的,但一种方法是使用 GestureService

            this.gestureListener = GestureService.GetGestureListener(containerPage);
            this.gestureListener.DragStarted += gestureListener_DragStarted;
            this.gestureListener.DragCompleted += gestureListener_DragCompleted;
            this.gestureListener.DragDelta += gestureListener_DragDelta;
    

    但是,它有一些错误。例如,DragCompleted 并不总是引发,因此您需要使用 ManipulationCompleted 事件仔细检查,这似乎更可靠。

            containerPage.ManipulationStarted += delegate { this.manipulationInProgress = true; };
            containerPage.ManipulationCompleted += delegate
            { 
                this.manipulationInProgress = false;
                PerformDragComplete(); 
            };
    

    另一个问题是 DragDelta 偶尔会报告错误的坐标。所以你需要这样的修复:

        Point refPosition = e.GetPosition(null);
        if (refPosition.X == 0 && refPosition.Y == 0)
        {
            Tracer.WriteLine("Skipping buggy event");
            return;
        }
    

    最后,你可以找到列表是否一直在顶部:

    public double VerticalOffset
    {
        get
        {
            ViewportControl viewportControl = this.FindChildByName("ViewportControl") as ViewportControl;
            if (viewportControl != null)
            {
                Tracer.WriteLine("ViewPort.Bounds.Top=" + viewportControl.Bounds.Top +  " ViewPort.Top=" + viewportControl.Viewport.Top.ToString() + " State=" + this.ManipulationState);
                return viewportControl.Bounds.Top - viewportControl.Viewport.Top;
            }
            return double.NaN;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多