2011-06-13 104 views
2

我对MVVM相对来说比较新,我想为MVVM WPF应用程序编写一个基本状态栏。我认为我有一些东西的要点,但出于某种原因,状态栏并不总是更新,我不知道为什么。StatusBar并不总是更新

在我的ViewModel,我有更新的基本属性,当我改变的状态消息:

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

我OnPropertyChanged方法(我在实现INotifyPropertyChanged基ViewModel类)看起来像这样(得到了冈瑟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> 

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

我看了几个使用ProgressBar控件的BackgroundWorker实例的例子,但没有看到任何StatusBarItem控件,并且我不确定如何将一个转换为另一个。我已经在之前的C#4.0和WPF应用程序中使用了任务,并且认为它可能是一个很好的方法,但我还没有真正弄清楚如何/在哪里指定UI任务(我称之为“我以前总是在MainWindow的代码隐藏中做到这一点,但我正在努力争取一个零代码保持与MVVM保持一致)。

我非常肯定,多线程方法是要走的路;我只是不太了解一种方法(我知道一点这个和一点点)以使其工作。我确实看到一些直接使用旧的线程方法的帖子,但是我几乎不用多线程编程,直到我开始使用.NET 4.0的任务(发现它们更易于理解和跟踪),所以我有有点麻烦使他们感觉。

任何人都可以怜悯我,并指出我在正确的方向,或建议进一步的调试,我可以做什么?谢谢!

+0

我有类似的更新TextBlock问题,你到底找到了解决方案吗? – 2011-06-14 08:01:57

+0

我**能够通过将我的UI TaskScheduler传递到ViewModel并对从所述调度程序生成的任务执行更新来获得任务代码的工作。如果时间允许,我会在单独的答案中发布代码示例。 – 2011-06-17 12:10:41

+0

@Julien,这就是我所做的。当我在我的App.xaml.cs文件中初始化我的ViewModel时,我传入了两个TaskFactory实例:一个用于UI:新的TaskFactory(TaskScheduler.FromCurrentSynchronizationContext())'我调用了'UiTasks',一个用于其他任务'任务.Factory'我称之为'DefaultTasks'。然后,我确定我的繁重工作在默认任务工厂下运行,并使用UI工厂更新了我的属性:'this.UiTasks.StartNew((=)this.StatusMessage = myMessage;});'这似乎是个诀窍。如果你愿意,我会很乐意给你一个更详细的例子。祝你好运! – 2011-06-19 14:04:04

回答

3

1)基于反射的绑定有时可能是内联错误的根源。尝试看看如果notifyproperty与简单的字符串而不是反射更改会发生什么。2)如果你正在使用多线程,那么你有可能在没有从UIThread中设置StatusMessage的情况下,它将无法更新UI,你可以在UI Dispatcher上调用setter代码来查看是否有帮助。

3)检查结合作品,XAML形式的构造是否修改StatusMessage直接在VM和看到的变化是否在UI显示而不调用其引入额外的变量,以简单正文块多线程服务呼叫 - 串结合

4)如果这没有帮助你可以创建一个简单的xaml表单与单个文本块绑定到您的大viewmodel,看看会发生什么,如果没有任何工作,你可以begi ñ切割VM类,使其更简单,从而结合最终开始工作,你会发现一个错误

5)如果你认为状态栏的问题是看是否没有状态栏单个文本块(摘录XAML部分从你的例子)的作品

+0

谢谢,瓦伦丁。事实证明,问题**是**状态消息没有从UI线程更新(当时我无法弄清楚如何用MVVM做到这一点)。一旦我能够在我的App_Startup例程中设置UI TaskScheduler/TaskFactory并将其传递到ViewModel的构造函数中,然后使用它产生一个Task来更新状态,它就像一个魅力一样工作。谢谢! – 2011-06-17 12:12:52

+0

我很困惑,为什么原产线是一个问题。 WPF是打算编组绑定到UI线程上的通知自动不是? – Gusdor 2011-07-27 10:11:16

2

某处通知没有通过。

我会尝试:

  • 添加一个虚拟valueconverter上textbinding所以你可以设置一个断点,看看你被称为
  • 在“更好的”时间调度的属性设置为设置的值 - 这有时是杞人忧天。

调度该设置可能会诀窍。