简体   繁体   English

从DataService MVVM Light持续更新ViewModel

[英]Continuous update of ViewModel from DataService MVVM Light

Originally my ViewModel had the following: 最初,我的ViewModel具有以下内容:

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

One of the commands ran this code 其中一个命令运行了此代码

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

But this doesn't work at design time. 但这在设计时不起作用。 So I moved the code into the DataService. 因此,我将代码移到了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);
                    }
                }

                );
        });            
    }

The DataService code looks like this 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;
        }
    }

But as far as I can tell there is no continuous communication channel between the DataService and the ViewModel. 但是据我所知,DataService和ViewModel之间没有连续的通信通道。 So with the new approach it reads all of the files and then displays it in the grid, but I want it to display each update as it goes. 因此,使用新方法,它会读取所有文件,然后将其显示在网格中,但是我希望它在进行时显示每个更新。

My instinct is to add a Messenger within the foreach and subscribe to it in the ViewModel, but there does not seem to be a way to use a messenger within a data service. 我的本能是在foreach中添加Messenger并在ViewModel中进行订阅,但是似乎没有一种在数据服务中使用Messenger的方法。

How can the DataService send a message to the ViewModel each time it has scanned a file? DataService每次扫描文件时如何将消息发送到ViewModel? Alternatively is there a better architecture for loading the data? 另外,是否有更好的架构来加载数据?

It turns out I was just missing the using statement for messenger and it is possible to update the ViewModel using it. 事实证明,我只是缺少Messenger的using语句,可以使用它来更新ViewModel。

In the ViewModel constructor I added 在ViewModel构造函数中,我添加了

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

and the ScanFolderAsync() method was updated to send the message 并且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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM