WPF按钮命令绑定已刷新,但按钮仍处于禁用状态

WPF按钮命令绑定已刷新,但按钮仍处于禁用状态,wpf,button,mvvm,command,canexecute,Wpf,Button,Mvvm,Command,Canexecute,我有一个奇怪的问题,按钮的命令绑定没有被更新 我有一个用MvvmLight编写的应用程序,允许用户维护医疗系统列表。这些系统是根据模板构建的(即模板可能指定两个摄像头、一个framegrabber等,以及每个部分应包含的详细信息)。如果修改了模板,则可以升级系统以使用新模板。“系统”窗口和“模板”窗口都是非模态的,因此可以在查看系统时修改模板。如果模板被更新,templates窗口视图模型将发送一条消息,以便任何打开的系统窗口都可以做出相应的反应 系统视图包含一个边框,用于在用户需要升级系统时警

我有一个奇怪的问题,按钮的命令绑定没有被更新

我有一个用MvvmLight编写的应用程序,允许用户维护医疗系统列表。这些系统是根据模板构建的(即模板可能指定两个摄像头、一个framegrabber等,以及每个部分应包含的详细信息)。如果修改了模板,则可以升级系统以使用新模板。“系统”窗口和“模板”窗口都是非模态的,因此可以在查看系统时修改模板。如果模板被更新,templates窗口视图模型将发送一条消息,以便任何打开的系统窗口都可以做出相应的反应

系统视图包含一个边框,用于在用户需要升级系统时警告用户。边框的可见性绑定到系统实体上的bool属性,该属性将系统的修订号与基础模板的最新修订号进行比较。如果它们位于最新的模板修订版上,则可见性设置为“折叠”,因此它们看不到内容

如果系统使用旧版本,则边框可见,内容中包含一条消息,通知他们需要升级,以及执行升级的按钮。我有三个关于这个边框和按钮的场景

<Border Visibility="{Binding Converter={StaticResource BoolToVisibilityVC}, Path=NotUsingLatestDhrTemplate, ConverterParameter=true}"
        HorizontalAlignment="Stretch"
        Margin="3"
        Grid.Row="3"
        BorderBrush="Red"
        BorderThickness="2"
        Background="#FFFFEBEB">
  <Grid Margin="3"
        gridHelper:GridHelper.GridRows="*,Auto">
    <WrapPanel>
      <TextBlock Text="This PCR uses template revision "
                  VerticalAlignment="Center" />
      <TextBlock Text="{Binding TemplateRevisionForThisDhr}"
                  VerticalAlignment="Center" />
      <TextBlock Text=", but the current template revision is "
                  VerticalAlignment="Center" />
      <TextBlock Text="{Binding LatestTemplateRevisionForThisPartDefinitionType}"
                  VerticalAlignment="Center" />
      <telerik:RadButton Name="UpdateDhrButton"
                          Click="UpdateDhrButton_OnClick"
                          Command="{Binding Path=DataContext.UpdateDhrCommand, ElementName=DhrViewX}"
                          Margin="0,0,10,0"
                          HorizontalAlignment="Right"
                          VerticalAlignment="Stretch"
                          IsEnabledChanged="UpdateDhrButton_IsEnabledChanged">
        <StackPanel Orientation="Horizontal"
                    Margin="1">
          <Image Margin="0,0,3,0"
                  Width="16"
                  Height="16"
                  Source="/Images;component/Images/battery.png" />
          <TextBlock>Update PCR</TextBlock>
        </StackPanel>
      </telerik:RadButton>
    </WrapPanel>
  </Grid>
</Border>
1) 如果在打开窗口时系统使用过期版本,则显示边框,并且按钮可见。如果修改了模板,则消息将正确更新以显示新号码,并且按钮将保持可见。这是正确的

2) 如果系统在打开时使用的是最新的模板修订版,则在修订模板时,边框将正确显示,消息将正确更新,并且按钮将启用。同样,这是正确的,只要我随后关闭系统窗口

3) 但是,如果单击“更新”按钮,则在系统升级并隐藏边框后,我将再次更新模板,然后在重新显示边框时,该按钮将被禁用。我尝试从CanExecute方法中删除所有逻辑并返回true,因此按钮应该被启用,但它没有。我必须关闭系统窗口并重新打开它以启用按钮

我尝试向视图模型添加一个事件,每当更新模板时都会引发该事件。我在视图中捕获了此事件,并手动刷新了按钮的命令绑定。但是,这并没有导致再次调用CanExecute方法,按钮仍然处于禁用状态

我意识到这一切都有点混乱,在没有看到整个过程的情况下很难调试,但我希望有人能给我一些线索。如果有帮助,这里是相关的代码

首先,边框、消息和按钮的XAML

<Border Visibility="{Binding Converter={StaticResource BoolToVisibilityVC}, Path=NotUsingLatestDhrTemplate, ConverterParameter=true}"
        HorizontalAlignment="Stretch"
        Margin="3"
        Grid.Row="3"
        BorderBrush="Red"
        BorderThickness="2"
        Background="#FFFFEBEB">
  <Grid Margin="3"
        gridHelper:GridHelper.GridRows="*,Auto">
    <WrapPanel>
      <TextBlock Text="This PCR uses template revision "
                  VerticalAlignment="Center" />
      <TextBlock Text="{Binding TemplateRevisionForThisDhr}"
                  VerticalAlignment="Center" />
      <TextBlock Text=", but the current template revision is "
                  VerticalAlignment="Center" />
      <TextBlock Text="{Binding LatestTemplateRevisionForThisPartDefinitionType}"
                  VerticalAlignment="Center" />
      <telerik:RadButton Name="UpdateDhrButton"
                          Click="UpdateDhrButton_OnClick"
                          Command="{Binding Path=DataContext.UpdateDhrCommand, ElementName=DhrViewX}"
                          Margin="0,0,10,0"
                          HorizontalAlignment="Right"
                          VerticalAlignment="Stretch"
                          IsEnabledChanged="UpdateDhrButton_IsEnabledChanged">
        <StackPanel Orientation="Horizontal"
                    Margin="1">
          <Image Margin="0,0,3,0"
                  Width="16"
                  Height="16"
                  Source="/Images;component/Images/battery.png" />
          <TextBlock>Update PCR</TextBlock>
        </StackPanel>
      </telerik:RadButton>
    </WrapPanel>
  </Grid>
</Border>

更新PCR
显示CanExecute方法没有任何意义,因为它目前只包含“return true;”

在边框的可见性和按钮的启用状态之间似乎存在一些奇怪的交互,这似乎覆盖了CanExecute方法的结果


有人有什么想法吗?如果我忘记在这里添加任何重要内容,请随时询问。提前谢谢。

好吧,虽然我不是100%确定问题出在哪里,但我很确定我知道,所以我会发布它,以防对其他人有所帮助

该问题似乎只是在某个点禁用按钮后才出现的。似乎只要我在命令上有一个CanExecute方法,那么即使它总是返回true,在绑定过程中按钮仍然会被暂时禁用。如果在包含按钮的边界控件的可见性设置为折叠时发生这种情况,那么无论CanExecute方法返回什么,按钮都不会被启用

我通过删除CanExecute方法来解决这个问题,并在不希望单击按钮时隐藏按钮。然后,每次显示边框时,我都手动将按钮的IsEnabled属性设置为true

这在这个特定的场景中起到了作用,因为按钮的使用是基于权限的,所以如果不允许他们单击它,不让他们看到也没关系。不过,在其他情况下,这仍然会造成问题,我不确定你会如何应对


希望这对其他人有所帮助。

如果您使用的是
RelayCommand
,请尝试调用
UpdateDhrCommand.RaiseCancecutechanged()当您的
CanExecute()
条件发生更改时,或显式调用刷新。感谢您的建议,但它没有帮助。CanExecute方法正在启动,只是按钮的IsEnabled属性没有更新。我认为这与父边界的可见性设置为“折叠”有关。这似乎阻止了按钮被重新启用,即使CanExecute方法说它应该被重新启用。