2016-05-18 4 views
0

Ursprünglich mein Ansichtsmodell hatte folgende:Kontinuierliche Aktualisierung des Ansichtsmodelles von Data MVVM Licht

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

Einer der Befehle lief diesen Code

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

Aber diese zur Design-Zeit nicht funktioniert. Also habe ich den Code in den DataService verschoben.

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

       ); 
     });    
    } 

Der Data Code sieht wie folgt aus

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

Aber soweit ich das beurteilen kann, gibt es keine kontinuierliche Kommunikationskanal zwischen dem Dataservice und der Ansichtsmodell. Mit dem neuen Ansatz liest es also alle Dateien und zeigt sie dann im Raster an, aber ich möchte, dass jedes Update so angezeigt wird, wie es läuft.

Mein Instinkt ist es, einen Messenger innerhalb der Foreach hinzuzufügen und im ViewModel zu abonnieren, aber es scheint keinen Weg zu geben, einen Messenger in einem Datendienst zu verwenden.

Wie kann der DataService jedes Mal, wenn er eine Datei gescannt hat, eine Nachricht an das ViewModel senden? Gibt es alternativ eine bessere Architektur zum Laden der Daten?

Antwort

0

Es stellt sich heraus, dass ich nur die using-Anweisung für Messenger fehlte, und es ist möglich, das ViewModel zu aktualisieren.

Im Ansichtsmodell Konstruktor habe ich

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

und die ScanFolderAsync() -Methode aktualisiert wurde, die Nachricht senden

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