2016-05-18 2 views
0

Первоначально мой ViewModel было следующее:Постоянное обновление ViewModel от DataService MVVM Light

public ObservableCollection<DataListItem> files { get; private set; } 

    private object _filesLock = new object(); 

    public MainViewModel(IDataService dataService) 
    { 
     files = new ObservableCollection<DataListItem>(); 
     BindingOperations.EnableCollectionSynchronization(files, _filesLock); 

     _dataService = dataService; 
    } 

Одна из команд побежал этот код

  await Task.Run(() => { 
       Parallel.ForEach(files, new ParallelOptions() { MaxDegreeOfParallelism = 2 }, (file) => 
       {      
        this.files.Add(new DataListItem(file)); 
       }); 
      }); 

Но это не работает во время разработки. Поэтому я переместил код в DataService.

public async void ScanFolder() 
    { 
     if (!CanScanFolder()) return; 

     files.Clear(); 

     await Task.Run(() => 
     { 
      _dataService.GetData(SelectedFolder, filter, IncludeSubs, (myfiles, error) => 
       { 
        if (error != null) 
        { 
         return; 
        } 
        foreach (var file in myfiles.files) 
        { 
         files.Add(file); 
        } 
       } 

       ); 
     });    
    } 

Код по DataService выглядит следующим образом

public async void GetData(string folder, string filter, bool includeSubs, Action<DataItem, Exception> callback) 
    { 
     // Use this to connect to the actual data service 
     var item = new DataItem(folder, filter, includeSubs); 
     await item.ScanFolderAsync(); 
     callback(item, null); 
    } 

    public async Task<bool> ScanFolderAsync() 
    { 
     try 
     { 
      var ret = new List<DataListItem>(); 
      var files = Directory.EnumerateFiles(folder, filter, includeSubs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); 
      await Task.Run(() => { 
       Parallel.ForEach(files, new ParallelOptions() { MaxDegreeOfParallelism = 2 }, (file) => 
       {      
        this.files.Add(new DataListItem(file)); 
       }); 
      }); 

      return true; 
     } 
     catch (Exception) 
     { 
      return false; 
     } 
    } 

Но, насколько я могу сказать, что не существует непрерывного канала связи между DataService и ViewModel. Таким образом, с новым подходом он считывает все файлы, а затем отображает его в сетке, но я хочу, чтобы он отображал каждое обновление по мере его появления.

Моим инстинктом является добавить Messenger в пределах foreach и подписаться на него в ViewModel, но, похоже, не существует способа использовать мессенджер в службе данных.

Как DataService может отправлять сообщение в ViewModel каждый раз, когда он сканирует файл? В качестве альтернативы, есть ли лучшая архитектура для загрузки данных?

ответ

0

Оказалось, что мне просто не хватает инструкции using для мессенджера, и с ее помощью можно обновить ViewModel.

В конструктор ViewModel я добавил

Messenger.Default.Register<DataListItem>(this, (item) => { files.Add(item); }); 

и метод ScanFolderAsync() был обновлен, чтобы отправить сообщение

using GalaSoft.MvvmLight.Messaging; 

public async Task<bool> ScanFolderAsync() 
{ 
    try 
    { 
     var ret = new List<DataListItem>(); 
     var files = Directory.EnumerateFiles(folder, filter, includeSubs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); 
     await Task.Run(() => { 
       Parallel.ForEach(files, new ParallelOptions() { MaxDegreeOfParallelism = 1 }, (file) => 
      { 
       var item = new DataListItem(file); 
       Messenger.Default.Send<DataListItem>(item); 
       this.files.Add(item); 
      }); 
     }); 

     return true; 
    } 
    catch (Exception) 
    { 
     return false; 
    } 
} 
Смежные вопросы