Search code examples
c#windowsuwpobservablecollectionautosuggest

No Items in Populated ObservableCollection when accessed from another class


I'm trying to access an ObservableCollection that has already been populated inside another class (the viewModel). However, it always returns with nothing inside the ObservableCollection. I need this so that the collection can be sorted and searched. Interestingly, when I load the same ObservableCollection into an AutoSuggestBox, it displays the items in the ObservableCollection…

The code for sorting the Collection:

protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        Frame currentFrame = Window.Current.Content as Frame;
        MainPage mainPage = currentFrame.Content as MainPage;
        mainPage.UpdateNavigationView(0);

        TasksViewModel viewModel = new TasksViewModel();
        int count = viewModel.searchableTaskTitles.Count();
        bool swapped = false;

        while (swapped == false)
        {
            swapped = true;
            int loopCount = 0;
            System.Diagnostics.Debug.WriteLine(count);
            while (loopCount + 1 != count + 1)
            {
                if (string.Compare(viewModel.searchableTaskTitles.ElementAt(loopCount), viewModel.searchableTaskTitles.ElementAt(loopCount + 1)) == 1)
                {
                    string a = viewModel.searchableTaskTitles[loopCount];
                    viewModel.searchableTaskTitles[loopCount] = viewModel.searchableTaskTitles[loopCount + 1];
                    viewModel.searchableTaskTitles[loopCount + 1] = a;
                    swapped = false;
                }
                loopCount = loopCount + 1;
            }
            loopCount = 0;
        }
    }

The code for getting the data:

public class TasksViewModel
    {

        public System.Collections.ObjectModel.ObservableCollection<string> searchableTaskTitles = new System.Collections.ObjectModel.ObservableCollection<string>();
        public List<string> taskTitles = new List<string>();

        public async void GetData()
        {
            string taskTitle;
            string taskImportance;
            string taskCompletion;
            string taskDesc;
            StorageFolder folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("Tasks", CreationCollisionOption.OpenIfExists);
            IReadOnlyCollection<StorageFile> fileNames = await folder.GetFilesAsync();

            foreach (StorageFile file in fileNames)
            {
                using (var inputStream = await file.OpenReadAsync())
                using (var classicStream = inputStream.AsStreamForRead())
                using (var streamReader = new StreamReader(classicStream))
                {
                    taskTitle = string.Format(streamReader.ReadLine());
                    taskImportance = string.Format(streamReader.ReadLine());
                    taskCompletion = string.Format(streamReader.ReadLine()) + "%";
                    taskDesc = string.Format(streamReader.ReadToEnd());
                }

                this.searchableTaskTitles.Add(taskTitle);

                this.taskTitles.Add(taskTitle);
            }
        }

        public TasksViewModel()
        {
            GetData();
        }
    }

Just in case... the code for SearchQuerySubmitted for the AutoSuggestBox:

private void SearchQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
        {
            if (args.ChosenSuggestion != null)
            {
                SearchAutoSuggestBox.Text = args.ChosenSuggestion.ToString();
                string searchText = args.ChosenSuggestion.ToString();

                int clickedItem = 0;
                TasksViewModel viewModel = new TasksViewModel();
                foreach (string item in viewModel.taskTitles)
                {
                    if (searchText == item)
                    {
                        clickedItem = viewModel.taskTitles.IndexOf(item);
                    }
                }
                System.Diagnostics.Debug.WriteLine(clickedItem);
                this.Frame.Navigate(typeof(ViewTaskPage), clickedItem);
            }
        }

Thank you very much!!!


Solution

  • In your search query submitted method you're doing this:

    TasksViewModel viewModel = new TasksViewModel();
    

    The constructor calls GetData but this returns a Task which as it doesn't have a return type, it can't be awaited, and you're not even trying to wait for it to finish either.

    You need to either ditch the async, or return a value and wait for it in the constructor.

    You shouldn't be doing async work in the constructor anyway, so my recommendation would be to change this code, to:

    TasksViewModel viewModel = new TasksViewModel();
    await viewModel.GetData();
    

    But be sure to have GetData actually return something, or awaiting won't work, because you can't await a void-returning async method.

    See MSDN for more information on how to properly use async / await