Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a looping/circular ScrollViewer in Windows 8 Metro (C++/XAML)

In a Windows 8 Metro app, is it possible to create a ScrollViewer which upon reaching the last item in the view, it loops back to the first item in the view? If so, how can I achieve this effect?

like image 294
PZS Avatar asked Jul 05 '12 12:07

PZS


People also ask

How to implement vertical scrolling in WPF ScrollViewer?

The WPF ScrollViewer control can be used to implement vertical and horizontal scrolling on Windows controls. To implement scrolling functionality on a content control, the content control is placed as the default content of a ScrollViewer control using its Content property.

How do I use a scroll viewer?

Scroll viewers enable content to extend beyond the bounds of the viewport (visible area). Users reach this content by manipulating the scroll viewer surface through touch, mousewheel, keyboard, or a gamepad, or by using the mouse or pen cursor to interact with the scroll viewer's scrollbar.

How do I use the ScrollViewer in WinUI 3 gallery?

Open the WinUI 3 Gallery app and see the ScrollViewer in action. The WinUI 3 Gallery app includes interactive examples of most WinUI 3 controls, features, and functionality. Get the app from the Microsoft Store or get the source code on GitHub To add vertical scrolling to your page, wrap the page content in a scroll viewer.

What are the XAML attached properties of a custom ScrollViewer?

ScrollViewer defines the following XAML attached properties: These XAML attached properties are intended for cases where the ScrollViewer is implicit, such as when the ScrollViewer exists in the default template for a ListView or GridView, and you want to be able to influence the scrolling behavior of the control without accessing template parts.


1 Answers

It is definitely possible. I am solving the problem at the moment and will post work when done. So far it goes something like below.

THe idea is that you hook into the viewchanged event for the scroll viewer, which fires anytime you move the bar. Once there, calculate where you are in the offset and the size of your items, and then you can use that to measure against the actual size of your listbox container or what have you.

Once you know where you are in the offset and know the actual height of your listbox and the height of your items, you know which items are currently visible and which are not. Make sure your list bound to the object is an observable collection implementing the INotifyChanged interface with two way binding. Then you can define a set of objects to rotate back and forth based on where in the scrolling you are.

Another option is to try a different starting point, perhaps a single control with a marquee and a scrollbar under it?

XAML

</UserControl.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
<ScrollViewer x:Name="ScrollViewer1">
    <ListBox x:Name="SampleListBox" Background="White" ItemsSource="{Binding Path=sampleItems}" ItemTemplate="{StaticResource sampleTemplate}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="0" Grid.RowSpan="2">

    </ListBox>
</ScrollViewer>
</Grid>

Code Behind

    public sealed partial class MainPage : Page
{
    List<SampleItem> sampleItems;
    const int numItems = 15;
    public MainPage()
    {
        sampleItems = new List<SampleItem>();
        for (int i = 0; i < numItems; i++)
        {
            sampleItems.Add(new SampleItem(i));
        }
        this.InitializeComponent();
        SampleListBox.ItemsSource = sampleItems;
        ScrollViewer1.ViewChanged += ScrollViewer1_ViewChanged;
    }
    void ScrollViewer1_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
    {
        ScrollViewer viewer = sender as ScrollViewer;
        ListBox box = viewer.Content as ListBox;
        ListBoxItem lbi = box.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
        double elementSize;
        if (lbi == null)
            return;
        elementSize = lbi.ActualHeight;

    }        /// <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)
    {
    }
}

public class SampleItem
{
    public String ItemCount { get; set; }
    public SampleItem(int itemCount)
    {
        ItemCount = itemCount.ToString();
    }
}
like image 199
Dev Dave Avatar answered Oct 31 '22 16:10

Dev Dave