2014-10-02 69 views
0

对于一个项目,我使用了一个非常简单的进度覆盖。UI无法从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> 

而且我有一个非常简单的事件,这只是设置了可视性(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秒加载。

所以我想在屏幕加载时显示我的Progress overlay。

这是行不通的。当这些事件被组合时,新的屏幕和覆盖图同时显示为 。

这就是:

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

为了调试原因,我没有停用进展覆盖到 发生了什么。

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

我已经发布ProgressingChange事件

  • 在这两个事件处理程序
  • 睡觉运行这两个事件对单独的线程
  • 只运行其中的一个在出版公布后试图

    我错过了什么?

    这里发生了什么?

    我怎样才能让它工作?

    CNC中

    这里是我的处理程序方法的代码:

    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 
    } 
    

    而且我用从上面链接的源代码,这迫使用户界面更新, 但没有奏效

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

    此外,我试图出版在临界段以迫使第一 p在第二个之前被执行,但是那也行不通。

    -edit2- 代码,至少显示进度覆盖

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

    Sleep()是没有用的,但发布你强制UI更新的方式。并且'Handle(ProgressingChange pc)' – 2014-10-02 09:54:42

    +0

    如果你的屏幕需要一段时间才能加载,那么你可能没有办法做 - 因为只有一个“UI线程”,它可能是度量/排列或元素生成的瓶颈。在这段时间内,可能会出现很多阻塞现象,阻止进度条显示,直到新屏幕中的组件完成生成(无新的呈现调用) - 值得张贴您的'处理'方法,以便我们可以查看在他们的内部,以防万一情况并非如此。我发现使用一些相当繁忙的第三方控件有时会锁定用户界面以进行简短的暂停... – Charleh 2014-10-02 10:22:04

    +0

    已添加代码,请查看 – 2014-10-02 10:28:31

    回答

    1

    这可能是一个黑客,但你可以尝试先等待边境(porgress巴)之前被渲染导航事件已发布。要做到这一点,你也许能够适应the solution that is given here执行一些代码当UI线程不再忙(见链接的完整说明):

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

    如果一切正常,那么至少你有什么要开始让代码更清洁一些。

    +0

    非常感谢您的回答。我在两次'Publish'调用之间放置了“hacky”代码行。但这不起作用。 – 2014-10-02 10:30:31

    +0

    你可以发布你试过的代码吗?目的是发布“TraceLine.Write”被调用的导航事件,以便只在渲染完成后立即发布导航事件。 – 2014-10-02 10:42:08

    +0

    工程!进度条被阻止,但至少有一个明确的信息表明正在发生一些事情! – 2014-10-02 10:50:43