【问题标题】:How can I prevent Scrollviewer to scroll back when scrollbarvisibility is set to disabled? wp7当滚动条可见性设置为禁用时,如何防止 Scrollviewer 向后滚动? wp7
【发布时间】:2012-05-04 16:40:54
【问题描述】:

我在 WP7 中创建了一个 Scrollviewer,它包含 3 个用户控件,每个用户控件都保存为 XAML 创建的用户控件的内容。这工作正常。此滚动查看器应该能够在这些项目之间滚动,但使用户无法滚动。因此,当单击这些内容之一中的项目时,滚动查看器会根据所选项目向左或向右滑动,并显示其他用户控件之一。我使用调解器来完成此操作:

<Grid.Resources>
        <Storyboard x:Name="ItemAnimation">
            <DoubleAnimation x:Name="ItemAnimationContent"
                             Storyboard.TargetName="Mediator"
                             Storyboard.TargetProperty="ScrollableWidthMultiplier"/>
        </Storyboard>
</Grid.Resources> 
<ScrollViewer Name="ScrollableItemPanel" 
                  Grid.Row="2" 
                  Grid.RowSpan="3" 
                  Grid.ColumnSpan="3"
                  VerticalScrollBarVisibility="Disabled"
                  HorizontalScrollBarVisibility="Disabled">

        <StackPanel Orientation="Horizontal">
            <UserControl    Name="NewsListBoxControl" Width="480" />
            <UserControl    Name="DetailedItemControl" Width="480"/>            
            <UserControl    Name="ExternalBrowserItemControl" Width="480"/>
        </StackPanel>
    </ScrollViewer>

    <local:ScrollableItemAnimationMediator x:Name="Mediator" 
                                           ScrollViewer="{Binding ElementName=ScrollableItemPanel}"/>

基本上,这也很好用,我可以在项目之间导航,并将内容作为用户控件加载到它们上。但问题在于授予用户滚动的能力。在项目滚动之前,我将 hittestvisibilty 设置为 true,并将 Horizo​​ntalscrollbarvisibility 设置为可见。动画完成后,我想授予 hittestvisibility 并再次将 Horizo​​ntalscrollbarvisibility 设置为 Disabled。后者是问题所在:当我将 Horizo​​ntalscrollbarvisibility 设置为 Disabled 时,scrollviewer 会自动将堆栈面板中的三个项目中的第一个带回到视图中。我怎样才能阻止这个?这是我用来滚动中介的代码:

private void CreateDetailedArticleItem( Dictionary<string, string> itemQuery )
    {
        _articleDetailPage.ItemQuery = itemQuery;
        DetailedItemControl.Content = _articleDetailPage as UserControl;
        Animate( _articleDetailPage, 0.0f, 0.5f, 250 );
    }

private void Animate( IContentControl control, float from, float to, double milliseconds )
    {                                                                                                                            
        //this eventhandler will fire when the animation has completed
        EventHandler handler = null;
        //we take away the User Input just for the moment, so that we can animate without the user interfering. Also, we make horizontalScroll Visible
        IsUserEnabled = false;

        //we then set the content of the animation. Where from will it move, towards where and in what duration?
        ItemAnimationContent.From = from;
        ItemAnimationContent.To = to;
        ItemAnimationContent.Duration = TimeSpan.FromMilliseconds( milliseconds );
        //we start the animation
        ItemAnimation.Begin( );

        //we tell the new control that it will appear soon, so it can load its main content
        control.ViewWillAppear( );
        //also, we tell the currentcontrol that it will disappear soon, so it can unload its content and eventhandlers and so on
        CurrentControl.ViewWillDisAppear( );

        //the handler is a delegate. This way, it becomes rather easy and clean to fire the completed event, without creating a strong reference ( well, actually,
        //we do create a strong reference, but as soon as it is fired, we remove it again, shhhh! ).
        handler = delegate( object sender, EventArgs e )
        {
            //as stated, we remove the eventlistener again, so it won't keep firing all the time
            ItemAnimation.Completed -= handler;

            //after the animation, we tell the new control that it is now in screen, and can start downloading its data
            control.ViewDidAppear( );
            //at the same time, the "current" control has fully moved out of view, so it can now fully unload all its content.
            CurrentControl.ViewDidDisAppear( );
            //now, all we have to do is to make sure that the next time an item is being loaded, the new content is spoken to, not the old one
            CurrentControl = control;

            //and finally, enable the users input again, and remove the horizontal scrollbarvisibility
            IsUserEnabled = true;                
        };            
        ItemAnimation.Completed += handler;
    }
 private bool IsUserEnabled
    {
        set
        {
            //when the user can control the scrollviewer, then the horizontal scrollvisibility is disabled, so that the user cannot move horizontally,
            //otherwise, so we only make it visible when the program needs to animate.
            ScrollableItemPanel.IsHitTestVisible = value;
            ScrollableItemPanel.HorizontalScrollBarVisibility = value ? ScrollBarVisibility.Disabled : ScrollBarVisibility.Visible;
        }
    }

我已经问过这个问题,然后将其视为已回答,因为我认为它已回答,即使用 ScrollbarVisibility.Hidden 而不是 ScrollbarVisibility.Disabled,只有滚动条可见性保持可见,并且用户仍然可以滚动。有本地方法来处理这个问题吗?

任何帮助将不胜感激。问候

【问题讨论】:

    标签: windows-phone-7 uiscrollview


    【解决方案1】:

    与其对抗本机控件的行为,不如使用自定义控件(包装您的其他控件)自己操纵项目的位置可能更容易,该控件根据“选择”项目。

    【讨论】:

    • 是的,我确实想到了这一点(在等待答案的同时处理其他事情),但认为可能存在原生的东西,这会节省我很多时间。但据你所知,scrollviewer的这个缺陷是没有办法绕过的,那我接受吗?
    • 这可以说不是控件的缺陷。你只是想把它用于它不是为它设计的东西。
    • 是的,没错,我只是觉得奇怪的是 Scrollbarvisibility 提供了两种隐藏可见性的方法,其中一种不会阻止滚动(我认为它只是隐藏了指示器滚动条)和另一种一个使它在将其设置为不可见后立即滚动回顶部。无论如何,我现在只是使用您建议的方法。谢谢=3
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-15
    • 1970-01-01
    • 2019-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-18
    相关资源
    最近更新 更多