WPF-视图模型通过后台工作程序更新属性,但视图在聚焦之前不会更新某些元素
视图模型正在使用模型中的后台工作线程异步加载数据。模型和视图模型中的所有属性都会引发属性更改事件,并且视图中的所有属性都会按预期进行更新,但两个按钮的WPF-视图模型通过后台工作程序更新属性,但视图在聚焦之前不会更新某些元素,wpf,mvvm,binding,backgroundworker,mvvm-light,Wpf,Mvvm,Binding,Backgroundworker,Mvvm Light,视图模型正在使用模型中的后台工作线程异步加载数据。模型和视图模型中的所有属性都会引发属性更改事件,并且视图中的所有属性都会按预期进行更新,但两个按钮的IsEnabled状态取决于加载的某些属性的结果除外 令人沮丧的是,只要我关注视图的任何部分,或者在属性更新后设置断点(创建延迟),那么按钮IsEnabled状态就会按预期更新。因此,这似乎是一个时间问题 关于如何找到解决这个问题的最佳方法,有什么线索吗?我使用的是mvvm轻型框架,但这不重要 我尝试将IsEnabled绑定到按钮,而不是仅仅依赖命
IsEnabled
状态取决于加载的某些属性的结果除外
令人沮丧的是,只要我关注视图的任何部分,或者在属性更新后设置断点(创建延迟),那么按钮IsEnabled
状态就会按预期更新。因此,这似乎是一个时间问题
关于如何找到解决这个问题的最佳方法,有什么线索吗?我使用的是mvvm轻型框架,但这不重要
我尝试将IsEnabled
绑定到按钮,而不是仅仅依赖命令
属性,但这没有什么区别。我已经通过日志确认设置了视图模型属性,并且正在为与按钮关联的属性引发PropertyChanged
事件
考虑使用mvvm light messenger在异步完成事件上从视图模型向视图发送消息,然后以某种方式?触发视图刷新,但这似乎是一个难题
更新
多亏了blindmeis的回答,我在没有命令绑定集的情况下测试了按钮的行为,即只绑定IsEnabled属性,并且它按照预期工作
<Button
Grid.Column="2" Content="{Binding LoadProjectsLabel}"
VerticalAlignment="Top" HorizontalAlignment="Right"
IsEnabled="{Binding CanLoadProjects}" />
变通办法
连接单击事件并避免命令
。从视图模型中解决它会很好,但这是可行的:
<Button
Grid.Column="2" Content="{Binding LoadProjectsLabel}"
VerticalAlignment="Top" HorizontalAlignment="Right"
IsEnabled="{Binding CanLoadProjects}"
Click="loadProjects_Click"/>
您应该将命令参数属性绑定到viewmodel上的任何可更新属性,并且可以执行必须使用此命令参数才能启用按钮。如果命令参数的目标被更新,绑定将根据can excute的返回值启用/禁用 其他人的回答:
BackgroundWorker完成后,调用CommandManager.InvalidateRequestSuggested()
默认情况下,WPF仅偶尔重新查询命令。否则,在每个ICommand实现上不断调用“CanExecute”会带来巨大的开销。调用上述方法将强制CommandManager立即更新
这将强制命令适当地重新启用/禁用
编辑:
我使用了一个简单但不太漂亮的解决方法。我只需在BackgroundWorker Completed事件中为我的命令调用PropertyChanged(“MyICommand”)
编辑:
是另一个很好的解决方案。正确,命令参数属性是视图模型上的一个属性。它是不可更新的,因为它是由模型中的逻辑设置的逻辑操作,但是模型属性正在引发一个事件,该事件将流到视图模型上属性的PropertyChanged事件。正如我所说,它正在工作,不管我是否使属性可设置/可更新(我已经尝试过),只有在我将焦点(例如,鼠标单击表单)放在视图上时,更新才会发生。这就像操作是在视图有机会刷新自身之前发生的。感谢blindmeis,这看起来应该可以解决问题,但也不起作用:(我还尝试将view model属性绑定到按钮的IsEnabled
属性,即避免使用命令CanExecute via mvvm light RelayCommand,可惜这也不起作用。但您的答案提供了线索,问题已更新:)+我将等待一段时间,看看是否有其他人可以通过w.r.t.命令
解决此问题。问题是,您的答案似乎应该可以解决此问题:-/不幸的是,当您为不存在的属性引发属性更改事件时,mvvm light会引发异常。?“MyICommand”只是ViewModel中ICommand属性的占位符。您必须使用propertyname当然:)嘿!我没那么傻;-)事实上,我在属性名中有一个输入错误,所以我可能是:D无论如何,该解决方案恢复为旧的(非工作)行为,即按钮IsEnabled
state(或Command.CanExecute)在窗口中的某个元素被聚焦之前不会更新。您使用的是什么类型的ICommand?它是在您的属性更改时启动CanExecuteChanged方法,还是它的CanExecuteChanged只是挂接到RequerySuggested?嗨,Joe,这是MVVM中的RelayCommand Light:我不确定您的其他问题:
public ICommand LoadProjectsCommand
{
get
{
if (_loadProjectsCommand == null)
{
_loadProjectsCommand = new RelayCommand(loadProjects, () => CanLoadProjects);
}
return _loadProjectsCommand;
}
}
<Button
Grid.Column="2" Content="{Binding LoadProjectsLabel}"
VerticalAlignment="Top" HorizontalAlignment="Right"
IsEnabled="{Binding CanLoadProjects}"
Click="loadProjects_Click"/>
void loadProjects_Click(object sender, RoutedEventArgs e)
{
SettingsViewModel vm = (SettingsViewModel)DataContext;
vm.LoadProjectsCommand.Execute(null);
}