Wpf UI未更新属性已用MVVM更改

Wpf UI未更新属性已用MVVM更改,wpf,inotifypropertychanged,updating,Wpf,Inotifypropertychanged,Updating,尽管UI组件的可见性绑定到ViewModel属性,并且实现了该属性的PropertyChanged,但UI是否可能跳过自身更新 视图/XAML: <Border Visibility="{Binding ShowLoadingPanel, Converter={StaticResource BoolToHiddenConverter}}"> <TextBlock Text="LOADING..." /> </Border> 从ViewMode

尽管UI组件的可见性绑定到ViewModel属性,并且实现了该属性的PropertyChanged,但UI是否可能跳过自身更新

视图/XAML:

 <Border Visibility="{Binding ShowLoadingPanel, Converter={StaticResource BoolToHiddenConverter}}">
      <TextBlock Text="LOADING..." />
 </Border>
从ViewModel运行以下操作时:

 ShowLoadingPanel = True
 RunBigTask()  'runs a task that takes a long time
 ShowLoadingPanel = False
…XAML中定义的边框不可见

但如果我添加了需要用户交互的内容,例如:

 ShowLoadingPanel = True
 MsgBox("Click to continue")
 RunBigTask()  'runs a task that takes a long time
 ShowLoadingPanel = False
。。。然后,边框将根据需要显示


这怎么可能呢?

你真的应该在后台线程中运行长时间运行的任务,因为它会阻止你的UI线程更新
可见性。。。实际上,
可见性
应该在长时间运行的任务完成时更新

用户经常使用
BackgroundWorker
对象来执行此操作。您可以在MSDN页面上找到完整的工作示例


BackgroundWorker
的常见替代方法是使用
Task
对象异步运行长时间运行的流程。您可以在MSDN的页面上找到使用
任务的完整工作示例。

您确实应该在后台线程中运行长时间运行的任务,因为它会阻止UI线程更新
可见性。。。实际上,
可见性
应该在长时间运行的任务完成时更新

用户经常使用
BackgroundWorker
对象来执行此操作。您可以在MSDN页面上找到完整的工作示例


BackgroundWorker
的常见替代方法是使用
Task
对象异步运行长时间运行的流程。您可以在MSDN的页面上找到使用
任务的完整工作示例。

您正在阻止调度程序,阻止布局更新。打开消息框时,会推送一个嵌套的消息循环,该循环允许调度器继续处理其队列,直到消息框关闭为止。布局更新正在该期间进行


在常规窗口上调用
ShowDialog()
时也会发生同样的情况:您的代码会被阻塞,但Dispatcher会继续运行,因此UI会按预期进行更新。在弹出嵌套消息循环之前,您的代码不会继续,这会在您关闭模式对话框(如消息框)时自动发生。

您正在阻止调度程序,从而阻止布局更新。打开消息框时,会推送一个嵌套的消息循环,该循环允许调度器继续处理其队列,直到消息框关闭为止。布局更新正在该期间进行

在常规窗口上调用
ShowDialog()
时也会发生同样的情况:您的代码会被阻塞,但Dispatcher会继续运行,因此UI会按预期进行更新。在弹出嵌套消息循环之前,您的代码不会继续,这会在您关闭模式对话框(如消息框)时自动发生。

我使用的是C#,在本例中,Visiblity不是布尔值,而是enum:System.Windows.Visibility,其值为Hidden/Visible/Collapsed

对于VB也是如此:公共属性可见性作为可见性

我使用的是C#,在我们的例子中,可见性不是布尔值,而是一个enum:System.Windows.Visibility,其值为Hidden/Visible/Collapsed


VB也是如此:公共属性可见性与可见性相同

是的,我知道我应该使用后台线程来执行长时间运行的任务。我只是想知道为什么在长时间运行的任务开始之前,在单个线程中,UI没有捕捉到ShowLoadingPanel=True更改并更新自身~就像程序运行太快,UI无法跟上一样。。。我不明白。对不起,我之前确实回复了你的评论,但网站上肯定有错误。。。除了@MikeStrobel所说的,程序的执行是逐行进行的。它不会将控制权返还给UI,直到它没有更多的行可以运行。我们可以通过使用异步方法和/或在后台线程上运行代码来“强制”这种情况[或者正如Mike所说,显示一个
MessageBox
]。我只是想知道为什么在长时间运行的任务开始之前,在单个线程中,UI没有捕捉到ShowLoadingPanel=True更改并更新自身~就像程序运行太快,UI无法跟上一样。。。我不明白。对不起,我之前确实回复了你的评论,但网站上肯定有错误。。。除了@MikeStrobel所说的,程序的执行是逐行进行的。它不会将控制权返还给UI,直到它没有更多的行可以运行。我们可以通过使用异步方法和/或在后台线程上运行代码来“强制”这种情况[或者正如Mike所说,显示一个
MessageBox
]。任何例子都会有帮助。那么,解决这个问题的变通方法/解决方案是什么呢。任何例子都会有帮助
 ShowLoadingPanel = True
 MsgBox("Click to continue")
 RunBigTask()  'runs a task that takes a long time
 ShowLoadingPanel = False