Caliburn Micro 在构造函数中开始协程 - 破坏视图?
我在 CM 中使用“视图模型优先”方法,创建一个 ViewModel 并在之后立即激活它。在 ViewModel 的构造函数中,我使用
以下方法启动协程: Coroutine.BeginExecute(Example().GetEnumerator());
我的视图中有一个繁忙指示器,并且我设置了 busy 属性(即绑定到繁忙指示器控件上的 IsBusy 属性的 TwoWay)为 true。当为 true 时,指示器显示;当为 false 时,它被隐藏。
所以我的协程看起来像这样:
IsBusy = true;
var example = client.AsyncOp();
yield return example;
var exampletwo = client.AnotherAsyncOp();
yield return exampletwo;
IsBusy = false;
问题似乎是 IsBusy 没有正确传播到视图。有时该指示器甚至不会显示。在其他情况下(最常见),指示器会显示,但即使在 IsBusy 设置为 false 后也不会关闭。
我不认为这是一个繁忙的指标问题,因为这种情况发生在各种其他属性上。例如,如果我设置了一个绑定到 ListBox 的 SelectedItem 的属性,则该属性将被设置,但 ListBox 不会将其显示为 GUI 中的 SelectedItem。
当协程最初执行时,Views 属性的计数为零,然后在第一次 yield return
后突然计数为 1。我可能是错的,但似乎存在某种竞争条件,CM 连接视图,而我设置属性。
我也尝试将协程移至 OnViewLoaded 事件,但仍然存在相同的问题,考虑到上一段,这很奇怪!
谢谢
I am using a View Model first approach with CM where I create a ViewModel and activate it immediately after. In the constructor of the ViewModel I am starting a coroutine using the method:
Coroutine.BeginExecute(Example().GetEnumerator());
I have a busy indicator in my views, and I set the busy property (that's TwoWay bound to the IsBusy property on the busy indicator control) to true. When true, the indicator shows; when false, it's hidden.
So my coroutine would look something like this:
IsBusy = true;
var example = client.AsyncOp();
yield return example;
var exampletwo = client.AnotherAsyncOp();
yield return exampletwo;
IsBusy = false;
The issue appears to be IsBusy not propagating to the view correctly. There are occasions when the indicator won't even show. There are other occasions (the most common) where the indicator will show, but won't turn off even after IsBusy is set to false.
I don't believe this is a busy indicator issue as this happens with various other properties. If, for example, I set a property that's bound to a ListBox's SelectedItem, the property will be set, but the ListBox won't show it as its SelectedItem in the GUI.
The Views property has a count of zero when the coroutine is initially executed, and then suddenly has a count of 1 after the first yield return
. I maybe wrong, but it seems like there's some kind of race condition going on where CM is hooking up the view, and me setting the properties.
I have also tried moving the Coroutine to the OnViewLoaded event, but that still has the same problems, which is curious considering the previous paragraph!
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是一个关于如何使用 CM 进行繁忙指示器的绝佳示例。
然后从你的协程中你可以执行以下操作:
This is an excellent example of how to do busy indicator with CM.
Then from your Coroutines you can do:
尽管您已经指出
client.AsyncOp();
和client.AnotherAsyncOp();
是异步的,但您没有显示实现,因此不清楚其中发生了什么那里。Caliburn.Micro 不会使操作异步,您仍然需要在
IResult
内完成工作,以便它不会在 UI 线程上执行,从而阻止您的 BusyIndicator。这里对协程有很好的解释,特别是<一href="http://gallery.jeremylikness.com/main.php?g2_view=core.DownloadItem&g2_itemId=222&g2_serialNumber=2" rel="nofollow">这张图希望能够更清楚地说明如何您的协程由框架执行。
Although you've indicated that
client.AsyncOp();
andclient.AnotherAsyncOp();
are async, you've not shown the implementation so it's not clear what's happening in there.Caliburn.Micro won't make an operation async, you still need to do the work inside your
IResult
so that it is not executed on the UI thread and therefore blocking your BusyIndicator.There's a really good explanation of coroutines here, in particular this diagram which should hopefully make it clearer how your coroutine gets executed by the framework.