UI不从EventAggregator更新

时间:2014-10-02 09:29:39

标签: c# wpf caliburn.micro eventaggregator

对于一个项目,我使用了一个非常简单的进度叠加。

它只显示一个小的选框进度条并覆盖屏幕。

所以在我的ShellView中我有

<Border Grid.Row="0"
        Grid.RowSpan="11"
        Grid.Column="0"
        Grid.ColumnSpan="11"
        HorizontalAlignment="Stretch"
        VerticalAlignment="Stretch"
        Panel.ZIndex="3"
        Background="#9E000000"
        BorderBrush="Black"
        BorderThickness="3"
        Visibility="{Binding IsProgressing,
                                 Converter={StaticResource BoolToVisibility}}">

        <!-- omitted progressbar, text etc -->
</Border>

我有一个非常简单的事件,它只设置了Visibility(IsProgressing)绑定和一些要显示的文本。

每当我想要一个进度条时,我只是发布那个事件,比如

_eventAggregator.Publish(new ProgressingChange(true, "Loading ..."));

到目前为止,除了一个案例之外,这项工作非常顺利:

对于应用程序,我使用事件来导航我的屏幕。

所以我发布了另一个事件,例如:

_eventAggregator.Publish(new NavigationEvent(typeof(TargetViewModel)));

只设置目标屏幕:

public void Handle(NavigationEvent navigate)
{
    var target = _screenFactory.FromType(navigate.TargetScreen);
    this.ActivateItem(target);
}

我的一个屏幕有很多项目,加载时间约为3秒。

所以我想在加载屏幕时显示我的进度叠加层。

这是行不通的。新的屏幕和叠加都是 同时显示这些事件的组合。

这是:

_eventAggregator.Publish(new ProgressingChange(true, "Loading ..."));
_eventAggregator.Publish(new NavigationEvent(typeof(LongLoadingViewModel)));

出于调试原因,我没有停用Progressing overlay到 发生了什么。

因此屏幕被加载,屏幕上没有任何显示约3秒钟,然后 显示进度叠加层和新屏幕。

我试过了

    发布ProgressingChange事件后
  • 休眠
  • 在两个事件处理程序中睡觉
  • 在不同的线程上运行两个事件的发布
  • 只在其他线程中运行其中一个发布
  • 尝试在force UI update
  • 强制执行此类UI更新

我错过了什么?

这里发生了什么?

我怎样才能让它发挥作用?

-edit -

以下是我的Handler方法的代码:

public void Handle(ProgressingChange progressing)
{
    this.IsProgressing= progressing.IsProgressing;
    this.ProgressingText= progressing.ProgressingText;
    NotifyOfPropertyChange(() => IsProgressing);
    NotifyOfPropertyChange(() => ProgressingText);  
    // of course, there is Notify in the setters themselves, too
}

我使用上面链接的源代码来强制UI更新, 但那不起作用

void AllowUIToUpdate() {

DispatcherFrame frame = new DispatcherFrame();

Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new DispatcherOperationCallback(delegate(object parameter)
{
    frame.Continue = false;

    return null;
}), null);

Dispatcher.PushFrame(frame);

}

另外,我尝试在一个关键部分发布以强制第一部分 发布在第二个之前执行,但这也不起作用。

-edit2 - 至少显示进度叠加的代码

_eventAggregator.Publish(new ProgressingChange(true, "Activating ..."));
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => _eventAggregator.Publish(new NavigationEvent(typeof(LongLoadingViewModel)))), DispatcherPriority.ContextIdle, null);

1 个答案:

答案 0 :(得分:1)

它可能是一个黑客攻击,但您可以尝试先在导航事件发布之前等待边框(porgress栏)呈现。为此,当UI线程不再繁忙时,您可以调整the solution that is given here来执行某些代码(请参阅链接以获取完整说明):

Dispatcher.BeginInvoke(new Action(() => Trace.WriteLine("DONE!", "Rendering")), DispatcherPriority.ContextIdle, null);

如果这样可行,那么至少你有一些东西要开始使代码更清洁。