Нет элементов в заполненной ObservableCollection при доступе из другого класса - PullRequest
0 голосов
/ 21 мая 2019

Я пытаюсь получить доступ к коллекции ObservableCollection, которая уже была заполнена в другом классе (viewModel).Тем не менее, он всегда возвращается ни с чем внутри ObservableCollection.Мне это нужно, чтобы коллекцию можно было сортировать и искать.Интересно, что когда я загружаю ту же ObservableCollection в AutoSuggestBox, она отображает элементы в ObservableCollection…

Код для сортировки коллекции:

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;
        }
    }

Код для получения данных:

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();
        }
    }

На всякий случай ... код для SearchQuerySubmitted для 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);
            }
        }

Большое спасибо !!!

Ответы [ 2 ]

1 голос
/ 21 мая 2019

В представленном вами методе поискового запроса вы делаете это:

TasksViewModel viewModel = new TasksViewModel();

Конструктор вызывает GetData, но это возвращает Task, который, поскольку у него нет возвращаемого типа, можетвас не ждут, и вы даже не пытаетесь дождаться его завершения.

Вам нужно либо прервать асинхронность, либо вернуть значение и дождаться его в конструкторе.

Вы все равно не должны выполнять асинхронную работу в конструкторе, поэтому я рекомендую изменить этот код на:

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

Но убедитесь, что GetData действительно что-то возвращает или ожидаетне будет работать, потому что вы не можете ожидать асинхронного метода, возвращающего пустоту.

См. MSDN для получения дополнительной информации о том, как правильно использовать async / await

0 голосов
/ 21 мая 2019

Вы не должны запускать асинхронную операцию в конструкторе. Это плохая практика .

Метод GetData() все еще работает, когда возвращается конструктор. Вместо того чтобы вызывать его в конструкторе, вы можете вызвать его из вашего OnNavigatedTo метода:

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

    TasksViewModel viewModel = new TasksViewModel();
    await viewModel.GetData();
    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;
    }
}

Вам также следует изменить тип возврата метода GetData() на Task, чтобы вы могли его ожидать. Метод async должен возвращать Task или Task<T>, если это не обработчик события. Пожалуйста, обратитесь к статье в журнале @Stephen Cleary для получения дополнительной информации о лучших практиках асинхронного программирования.

...