从IActivatableViewModel

问题描述

我正在使用AvaloniaUI框架来构建应用程序。
我有一个实现IActivatableviewmodelviewmodel,并在viewmodel构造函数调用WhenActivated我有一个定义的方法HandleActivation,该方法在激活视图模型时被调用,在HandleDeactivation时被取消激活。一切都被正确调用,那里没有问题。

它看起来像这样:

public abstract class Myviewmodel: viewmodelBase,IActivatableviewmodel
    {
        public viewmodelActivator Activator { get; }

        protected Myviewmodel() : base()
        {
            Activator = new viewmodelActivator();
            this.WhenActivated(disposables =>
            {
                this.HandleActivation();

                disposable
                    .Create(this.HandleDeactivation)
                    .disposeWith(disposables);
            });
        }

        private void HandleActivation()
        { }

        private void HandleDeactivation()
        { }
    }

我还有一个数据服务,可以从数据库中检索一些数据。我要调用方法返回一个Task<T>。 看起来像这样:

public interface IDataService 
{
     Task<IList<UserDto>> GetActiveUsers();
}

我想做的是从HandleActivation方法调用GetActiveUsers。我需要获取用户列表,然后在检索用户后对其进行一些后处理。
如果我使用异步方法执行此操作,那么我会执行类似的操作

private async Task HandleActivation()
{
    var users = await _dataService.GetActiveUsers();
    foreach(var user in users)
    {
       //do stuff
    }
}

由于HandleActivation不是异步方法,我对如何执行此操作感到有些困惑。
有没有一种方法可以使HandleActivation异步,有没有针对我的“反应性”方法? 我对AvaloniaUI和ReactiveUI以及响应式编程本身是非常陌生的,所以我确定有一种“正确”的方法可以做到这一点,但是我很难弄清楚。

解决方法

第一个代码片段中有关激活和停用的处理模式与ReactiveUI文档中的示例相匹配,但是没有人阻止您编写异步的HandleActivation方法,因此它看起来像这样:

    protected MyViewModel() : base()
    {
        Activator = new ViewModelActivator();

        this.WhenActivated(disposables =>
        {
            this.HandleActivation().ConfigureAwait(false);

            Disposable
                .Create(this.HandleDeactivation)
                .DisposeWith(disposables);
        });
    }

    private async Task HandleActivation()
    {
        var users = await Task<IEnumerable<UserDto>>.Factory.StartNew(() => _dataService.GetActiveUsers().Result);

        foreach (var user in users)
        {
            // do stuff
        }
    }

使用可观察对象的更具反应性的方法如下:

    protected MyViewModel() : base()
    {
        Activator = new ViewModelActivator();

        this.WhenActivated(disposables =>
        {
            this.HandleActivation();

            Disposable
                .Create(this.HandleDeactivation)
                .DisposeWith(disposables);
        });
    }


    private void HandleActivation()
    {
        Observable.Start(() => _dataService.GetActiveUsers().Result)
            .ObserveOn(RxApp.MainThreadScheduler) // schedule back to main scheduler only if the 'stuff to do' is on ui thread
            .Subscribe(users => DoStuffWithTheUsers(users));
    }

    private void DoStuffWithTheUsers(IEnumerable<UserDto> users)
    {
        foreach (var user in users)
        {
            // do stuff
        }
    }

如果GetActiveUsers本身是返回IList的同步方法,则它甚至可以异步工作,因为Observable.Start已经异步调用了该方法。该代码示例中的唯一区别是必须删除“ .Result”。

,

处理此类模式的另一种方法是使用Boolean。反应性命令很棒,它们使您能够管理长时间运行的异步操作。 reactive command允许您订阅bool[] boolArray = {false,true,false,false}; newTile = new Tile(1,3,1,12,-1,boolArray,-1); ReactiveCommand<Unit,Unit>的观察对象,并让用户知道您的应用程序在做什么。另外,反应式命令支持cancelation。因此,我可能建议您将激活逻辑移至名为例如IsExecuting,将停用逻辑转移到名为ThrownExceptions的反应式命令中,然后在Activate块中,您可以执行以下操作:

Deactivate

另请参阅this StackOverflow question

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...