如何解决从IActivatableViewModel
我正在使用AvaloniaUI框架来构建应用程序。
我有一个实现IActivatableViewModel
的viewmodel,并在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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。