StatusBar并不总是更新

时间:2011-06-13 17:32:58

标签: wpf multithreading mvvm c#-4.0

我对MVVM比较陌生,我正在尝试为MVVM WPF应用程序编写基本状态栏。我认为我有一些事情的要点,但由于某种原因,状态栏并不总是更新,我不知道为什么。

在我的ViewModel中,我有一个基本属性,我在更改状态消息时会更新:

public string StatusMessage
{
    get { return _statusMessage; }
    set
    {
        if (value == _statusMessage) return;
        _statusMessage = value;
        base.OnPropertyChanged(() => this.StatusMessage);
    }
}

我的OnPropertyChanged方法(我在一个实现INotifyPropertyChanged的基础ViewModel类中)看起来像这样(从Gunther Foidl得到这个想法;希望我可以声称它的功劳因为我认为它很光滑但我不是那么聪明):

protected virtual void OnPropertyChanged<T>(Expression<Func<T>> exp)
    {
    MemberExpression me = exp.Body as MemberExpression;
    string propName = me.Member.Name;

    PropertyChangedEventHandler handler = this.PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propName));
    }
}

无论如何,这一切都适用于我的所有控件,除了一个。在我的MainWindow.xaml文件中,我有一个StatusBarItem控件绑定到上面的属性,就像这样(由于空间原因,XAML的其余部分已被修剪):

<StatusBarItem Grid.Column="0">
    <TextBlock TextTrimming="CharacterEllipsis" Text="{Binding Path=StatusMessage}" />
</StatusBarItem>

当我运行我的应用程序(除了从模板和其他一些资源密集型的东西生成文档之外,它还会遇到几个DB),一些(但不是全部)消息显示在状态栏上。我已经调试并验证了消息都进入上面的StatusMessage属性(以及随后的私有变量),它们在UI中似乎没有刷新。

我已经看了几个使用BackgroundWorker实例进行ProgressBar控件的示例,但是没有看到任何StatusBarItem控件,并且我不确定如何将一个转换为另一个。

我之前在C#4.0和WPF应用程序中也使用过任务,并认为它可能是一个很好的方法,但我还没有真正弄清楚如何/在哪里指定UI任务(我已经以前总是在MainWindow的代码隐藏中完成它,但我正在努力寻找零代码,以便与MVVM保持一致)。

我很确定多线程方法是可行的方法;我只是不太了解一种方法(我知道这一点和一点点)使其工作。我确实看到了一些直接使用较旧的线程方法的帖子,但我几乎远离多线程编程,直到我开始使用.NET 4.0的任务(发现它们更容易理解和跟踪),所以我有理解它们有点麻烦。

任何人都可以对我表示同情并指出正确的方向,或建议我可以做进一步的调试吗?谢谢!

2 个答案:

答案 0 :(得分:3)

1)基于反射的绑定有时会因为内联而成为错误的来源。试着看看如果你没有使用简单的字符串而不是反射来改变会发生什么。

2)如果你使用的是多线程,你可能有可能不是从UIThread设置StatusMessage,那么它将无法更新UI,你可以在UI Dispatcher上调用setter代码来查看是否有帮助

3)检查绑定是否有效,在xaml表单的构造函数中直接在VM上修改StatusMessage并查看是否在UI上显示更改而不调用多线程服务调用,这些调用会向简单文本块引入其他变量 - 字符串绑定

4)如果这没有帮助你可以用单个文本块创建一个简单的xaml表单将它绑定到你的大视图模型并看看会发生什么,如果什么都不起作用你可以开始削减VM类以使其更简单所以绑定最终开始工作,你发现错误

5)如果您认为状态栏是问题,请查看没有状态栏的单个文本块(从示例中提取xaml部分)是否有效

答案 1 :(得分:2)

某处通知无法通过。

我会尝试:

  • 在文本绑定上添加虚拟值转换器,以便设置断点并查看是否被调用
  • 调度属性集以将值设置为“更好”的时间 - 这有时是非常的。

调度集可能会有所帮助。