为啥我工作时状态栏没有更新?
Posted
技术标签:
【中文标题】为啥我工作时状态栏没有更新?【英文标题】:Why isn't my StatusBar updating while I do work?为什么我工作时状态栏没有更新? 【发布时间】:2011-12-14 22:18:02 【问题描述】:我想在我的应用程序中添加一个状态栏,但我不知道最好的解决方案是什么?我正在将 c# 与 WPF 和模型 MVVM 一起使用。
现在我有一个部分可行的解决方案。问题是状态栏没有像我希望的那样经常更新。 例如,当我将一个新值写入状态栏绑定的字符串时,状态栏将更新得太晚,并希望显示任何差异。
一个简单的例子(不是真实的代码):
StatusBar 绑定到状态并且初始 = 就绪。
状态 = 正在下载
下载方式
状态 = 就绪
这不会导致视觉上的变化。当我调试代码时,状态的值会更新,但不会在状态栏中更改。
你有什么建议吗?
我的代码
XAML 视图:MainView.xaml
<StatusBar DockPanel.Dock="Bottom" >
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid Margin="0 -5 0 0">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem Grid.Column="0">
<TextBlock Name="statusBarStatus" Text="Binding Status"></TextBlock>
</StatusBarItem>
</StatusBar>
MainViewModel 的一部分
private void UpdateDepartmentsExecute()
Status = "Updating...";
repository.ShowAppDep = ShowAppDep;
repository.ShowInDep = ShowInDep;
repository.ShowSisDep = ShowSisDep;
repository.getPriority1 = SetPriorityTo1;
repository.getPriority2 = SetPriorityTo2;
repository.getPriority3 = SetPriorityTo3;
repository.getPriority4 = SetPriorityTo4;
repository.getPriority5 = SetPriorityTo5;
repository.UpdateTasksToShow();
repository.UpdateWorkareas();
repository.UpdateEmployees();
repository.UpdateTasksToShowByEmployee();
repository.UpdateWorkAreaByEmployee();
repository.GenerateStatistics();
TasksToShowCount = repository.TasksToShow.Count();
if (SelectedView == new Uri("pack://application:,,,/View/EstimateLoadView.xaml"))
MessageBox.Show("The Gantt Chart wan't show all relations when you are filtering the data. This might be a source to errors.", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
SelectedView = new Uri("pack://application:,,,/View/EntryView.xaml");
Status = "Ready";
【问题讨论】:
你能把你的视图和视图模型代码贴出来 我同意 devdigital。请发布课程或至少发布您绑定的属性。我已经使用了带有 MVVM 和转换器的状态栏,并且从未遇到任何问题。我假设您的 INotifyPropertyChanged 可能无效,或者您的应用程序太忙以至于 UI 线程无法赶上刷新可能由线程操作导致的 UI。 谁需要代码?他在 UI 线程上做所有事情,在他完成之前阻止对栏的更新。 那么如果我实现多线程它会工作吗? 【参考方案1】:您必须在后台线程中进行下载,最简单的方法是使用 BackgroundWorker 组件。否则,您的下载将发生在 UI 线程中,这意味着您的阻塞消息正在泵送和重新绘制。阻止这意味着您的 UI 不会更新,更糟糕的是可能意味着 Windows 认为您的应用程序没有响应。
要更新绑定到 UI 线程的集合,您应该能够使用 ReportProgress 事件并传递一些数据,然后处理程序可以使用这些数据来更新 OC。 ReportProgress 处理程序将被编组到适当的 UI 线程。
【讨论】:
好吧...到此为止。唯一的问题是下载方法在我绑定到 UI 的 ObervalCollection 中进行编辑。所以它想让我做改变。你有什么建议吗?【参考方案2】:使用后台线程中的调度程序(假设您正在同时运行状态更新!)。这是一篇不错的博文:Updating UI from a background thread
【讨论】:
我想这样做,但我现在没有。在您发给我的示例中,我不知道如何执行此部分:runner.RequestFinished。我找不到任何名为 RequestFinished 的想法? 还有一件事。如何从后面的代码中调用 ModelView 提供的方法?如果我想创建一个后台线程,这个接缝非常重要,因为我只能从后面的代码调用开始调用。还是我错了? 该示例使用事件处理程序方法(它订阅名为 RequestFinished 的事件),但在您的情况下,您可以从其他方法进行 BeginInvoke 调用。例如,您用于更新状态的方法(再次假设您在后台线程中运行它!)【参考方案3】:您不能绑定到Properties.Settings.Default
。因此,如果您希望 DataBinding 工作,您应该绑定到实现 INotifyPropertyChanged 的类的属性,在您的情况下。
在同一个链接页面上,您还应该看到一个示例,说明如何执行此操作。
像 Lauri 建议的那样,还要添加非 UI 阻塞调用,以便让您的 UI 有“呼吸”的可能性。
【讨论】:
现在我已经在我的存储库private string status = "Loading..."; public string Status get return status; set status = value; Notify("Status");
中添加了一个新变量,并将视图中的绑定编辑到这个<StatusBarItem Grid.Column="0"> <TextBlock Name="statusBarStatus" Text="Binding Status"></TextBlock> </StatusBarItem>
中,并且我的视图模型已经得到了这个变量,每当我想要更改状态消息。
public string Status get return repository.Status; set repository.Status = value;
应用启动时获取值,但没有获取任何更新???
刚刚将通知移动到我的 ViewModel 中,现在它又可以部分工作了。它正在获取状态消息的更改,但只是其中的最后一个。不是代码开头的那个。
您只看到“就绪”,所以最终结果,只是因为您在“长时间运行的操作”中阻止了 UI。在其他线程上运行该操作,您将看到您希望出现在状态栏上的文本。显然,您需要使用主 UI 线程调整不同线程的工作。以上是关于为啥我工作时状态栏没有更新?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 iPhone GPS 箭头出现在状态栏中,即使我没有在位置管理器上调用 startUpdatingLocation?