我有一个MVVM模型
查看
<StatusBar>
<StatusBarItem>
<TextBlock Text="{Binding Status, UpdateSourceTrigger=PropertyChanged}" Width="Auto"/>
</StatusBarItem>
</StatusBar>
视图模型
ViewModel()
{
public string Status { get; set; }
void UpdateProcess()
{
UpdateStatus("Updating Database");
Thread.Sleep(TimeSpan.FromSeconds(5));
UpdateStatus("Database updated");
}
void UpdateStatus(string message)
{
Status = message;
OnPropertyChanged("Status");
}
}
当应用程序运行时,它仅在“正在更新数据库”之后显示“正在更新数据库”而不是“数据库更新”。 似乎只有在UpdateProcess方法运行
后才能更新视图我需要在属性更改后立即更新视图。这可能吗?
即使我逐步调试代码,UI在通过第一个OnPropertyChanged时也不会更新。一旦整个UpdateProcess()完成,UI就会变为“”数据库更新“。
答案 0 :(得分:1)
一旦内部值发生变化,您可以展开Status属性的setter以引发PropertyChanged
private string _status;
public string Status
{
get
{
return _status;
}
set
{
_status = value;
OnPropertyChanged("Status");
}
}
当您设置Status属性时,PropertyChanged将触发并通知UI更新字段。
除了创建控件之外,这是WPF从绑定更新控件值的唯一方法。
可能产生影响的东西是绑定模式。
<StatusBar>
<StatusBarItem>
<TextBlock Text="{Binding Status, UpdateSourceTrigger=PropertyChanged}, Mode=TwoWay" Width="Auto"/>
</StatusBarItem>
</StatusBar>
您可以查看here以查看更好的模式说明
答案 1 :(得分:1)
我认为问题在于您在长时间运行期间尝试显示状态消息,但它们没有显示出来。这很可能是因为您的长时间运行操作正在执行(并因此阻止)UI线程。当UI线程被阻止时,UI上的任何内容都不会更新;事实上,如果你长时间保持阻止,Windows会建议用户你的应用程序已经停止响应,应该关闭。
如果你使用的是带有async / await的C#版本,你可以这样做:
private async Task UpdateProcess()
{
UpdateStatus("Updating Database");
await Task.Run(UpdateDatabaseMethod);
UpdateStatus("Database updated");
}
private void UpdateDatabaseMethod()
{
//Do long-running stuff in background...
//Note that this will no longer be executing in the UI thread
//so you may need to watch out for thread safety issues that you could previously ignore
//This might mean adding some locks around your database access methods...
}
对于异步/等待支持之前的版本,请查看BackgroundWorker。
需要警惕的是,您现在正在后台线程中运行长时间运行的任务,这与阻止UI时的行为不同。这可能会带来许多新的挑战和麻烦,但不幸的是,如果您想要与长时间运行的任务并行运行UI,那么这是一个必要的恶魔。
其他问题包括用户现在可以在更新数据库时单击其他内容。如果您需要阻止UI交互,则需要一些其他机制来禁用在长时间运行操作时可能会干扰的控件。一种典型的方法是使用类似这样的状态消息的某种“忙碌指示器”对话框。