locked
async and ScrollIntoView

    Question

  • Hi,

    I have the following code (just a snippet from a bigger app - itemId is an ID of an item I want to scroll the ItemsGridView to):

    var items = await GetItemsAsync();
    ItemsGridView.ItemsSource = items;
    
    ItemViewModel selectedItem = items.Where(it => it.ID == itemId).FirstOrDefault();
    
    // Select the current item.
    ItemsGridView.SelectedItem = selectedItem;
    
    if (selectedLot != null)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            ItemsGridView.ScrollIntoView(selectedItem);
        });
    }


    When I run this code the ItemsGridView.ScrollIntoView throws an unspecified error (HRESULT = -2147467259). The reason is that the data is retrieved asynchronously and apparently there is a problem with scrolling to a collection that is being retrieved async.

    A quick solution would be to wait until the data is retrieved and then use ItemsGridView.ScrollIntoView, something like that:

    var items = await GetItemsAsync();
    ItemsGridView.ItemsSource = items;
    
    ItemViewModel selectedItem = items.Where(it => it.ID == itemId).FirstOrDefault();
    
    // Select the current item.
    ItemsGridView.SelectedItem = selectedItem;
    
    if (selectedLot != null)
    {
        TimeSpan period = TimeSpan.FromMilliseconds(500);
    
        Windows.System.Threading.ThreadPoolTimer.CreateTimer(async (source) => 
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                ItemsGridView.ScrollIntoView(selectedItem);
            });
        }
        ,period);
    }

    It is an ugly solution but it works.

    I'm wondering if there is any more robust way to use ItemsGridView.ScrollIntoView with collections that are retrieved asynchronously.

    Thanks,

    Leszek


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com

    Wednesday, May 21, 2014 3:56 PM

All replies

  • Hi,

    The ItemsGridView.ScrollIntoView cannot work if the item cannot loaded. You might want to subscribe to the ItemContainerGenerator.ItemsChanged event to be sure that your items are loaded before scrolling.

    Best Wishes!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey. Thanks<br/> MSDN Community Support<br/> <br/> Please remember to &quot;Mark as Answer&quot; the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Thursday, May 22, 2014 3:01 AM
  • Thanks for your suggestion. Do you have any code snippets of the ItemContainerGenerator.ItemsChanged event handler that would be useful in scrolling a GridView with ItemsGridView.ScrollIntoView?

    Thanks,

    Leszek


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com

    Thursday, May 22, 2014 3:53 PM
  • Hi,

    You can code like below:

     
    public MainPage()
            {
                this.InitializeComponent();
                gridView.ItemContainerGenerator.ItemsChanged += OnItemsChanged;
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
    
                test.Add(new Test { Image = "Assets/image.png" }); test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
    
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
    
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                test.Add(new Test { Image = "Assets/image.png" });
                gridView.DataContext = test;
                gridView.SelectedItem = test[8];
               
                   
            }
     public async void OnItemsChanged(object sender, ItemsChangedEventArgs e)
            {
                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
           
    {
               
    ItemsGridView.ScrollIntoView(selectedItem);
           
    });
    }

    Best Wishes!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey. Thanks<br/> MSDN Community Support<br/> <br/> Please remember to &quot;Mark as Answer&quot; the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Friday, May 23, 2014 6:22 AM
  • Thanks Anne.

    After the changes you suggested my code looks like this:

    public MyPage()
    {
        this.InitializeComponent();
    
        Loaded += MyPage_Loaded;
        ItemsGridView.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged;
    }
    
    async void MyPage_Loaded(object sender, RoutedEventArgs e)
    {
        var items = await GetItemsAsync();
        ItemsGridView.ItemsSource = items;
    
        // Grab the selected item from the collection.
        ItemViewModel selectedItem = items.Where(it => it.ID == itemId).FirstOrDefault();
    
        // Select the current item.
        ItemsGridView.SelectedItem = selectedItem;
    }
    
    async void ItemContainerGenerator_ItemsChanged(object sender, ItemsChangedEventArgs e)
    {
        var col = ItemsGridView.ItemsSource as ObservableCollection<ItemViewModel>;
    
        // Grab the selected item from the collection.
        ItemViewModel selectedItem = items.Where(it => it.ID == itemId).FirstOrDefault();
    
        if (selectedItem != null)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                ItemsGridView.ScrollIntoView(selectedItem);
            });
        }
    }

    It still does not work. The line 

    ItemsGridView.ScrollIntoView(selectedItem)

    throws an "Unspecified error" exception each and every time.

    Thanks,

    Leszek


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com

    Friday, May 23, 2014 1:49 PM
  • Hi,

    Would you mind sharing a project which can reproduce the issue in the forum?

    Best Wishes!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey. Thanks<br/> MSDN Community Support<br/> <br/> Please remember to &quot;Mark as Answer&quot; the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.


    Tuesday, May 27, 2014 3:41 AM
  • This is a real-life project that comprises many layers built using MVVM. I don't have time at this moment to extract the code in order to reproduce the issue. I  need to move on using the poor solution with the Timer.

    I will get back to that later.

    Thanks


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com

    Thursday, May 29, 2014 3:04 AM