Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WPF-视图模型通过后台工作程序更新属性,但视图在聚焦之前不会更新某些元素_Wpf_Mvvm_Binding_Backgroundworker_Mvvm Light - Fatal编程技术网

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);
}