C# 为什么WPF按钮不总是触发其绑定命令?

C# 为什么WPF按钮不总是触发其绑定命令?,c#,wpf,wpf-controls,prism,C#,Wpf,Wpf Controls,Prism,我有一个用户控件,它是使用Prism编写的应用程序的一部分。它有一个“后退”按钮: <Button Content="Back" Command="{Binding BackCommand}" Padding="5 12 5 2" /> 此外,用户控件还有一个“下一步”按钮,该按钮根据用户在第二个控件中选择的内容移动用户通过一系列分支问题。“后退”按钮应该将用户带到上一个问题。后退按钮通常执行绑定命令,因此我知道绑定是有效的。有时,用户必须单击“上一

我有一个用户控件,它是使用Prism编写的应用程序的一部分。它有一个“后退”按钮:

<Button Content="Back"
        Command="{Binding BackCommand}"
        Padding="5 12 5 2" />
此外,用户控件还有一个“下一步”按钮,该按钮根据用户在第二个控件中选择的内容移动用户通过一系列分支问题。“后退”按钮应该将用户带到上一个问题。后退按钮通常执行绑定命令,因此我知道绑定是有效的。有时,用户必须单击“上一步”按钮两次,命令才会触发。我替换了CanExecute主体以始终返回true(如上所示),但按钮仍然停止工作

我在按钮上放置了临时事件处理程序,发现当命令无法执行时:

  • 该按钮已启用
  • 绑定仍在设置中
  • 按钮上的PreviewMouseDown事件将激发
  • 单击事件不会触发(即使我删除了该命令)
  • 未调用命令的Execute方法
每个问题,所以我发现命令没有开火,OP有一个或另一个绑定命令的问题。因为我的命令是绑定的,所以我没有发现太多有用的东西


编辑2:我已经找到了问题的原因。组成应用程序的组件之一是试图控制焦点。要复制问题,请将其粘贴到窗口中:

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Current count:"/>
        <TextBlock Text="{Binding Counter}"/>
    </StackPanel>
    <CheckBox x:Name="MyCheckbox" IsChecked="{Binding MaintainFocus}" LostFocus="MaintainFocus" >Maintain Focus</CheckBox>
    <Button Command="{Binding MyCommand}" Content="Test" Width="100" />
</StackPanel>

现在,如果选中保持焦点复选框,测试按钮将不会启动。

单击
图像应引发
单击事件。但是,如果您设置了
填充
属性并在实际的
图像
之外单击,则不会引发
单击
事件

您可以通过将
边框
元素放置在
网格
中,并使用
透明
背景来解决此问题:

<Style TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Background="Transparent">
                    <Border BorderThickness="0"
                            Background="Transparent"
                            Margin="{TemplateBinding Control.Padding}">
                        <Image Name="Image"
                               Source="{Binding NormalImage, RelativeSource={RelativeSource TemplatedParent}}" />
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed"
                                 Value="True">
                        <Setter TargetName="Image"
                                Property="Source"
                                Value="{Binding PressedImage, RelativeSource={RelativeSource TemplatedParent}}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>


但请注意,当您提出问题时,应始终提供问题的详细信息。

单击
图像应引发
单击事件。但是,如果您设置了
填充
属性并在实际的
图像
之外单击,则不会引发
单击
事件

您可以通过将
边框
元素放置在
网格
中,并使用
透明
背景来解决此问题:

<Style TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Background="Transparent">
                    <Border BorderThickness="0"
                            Background="Transparent"
                            Margin="{TemplateBinding Control.Padding}">
                        <Image Name="Image"
                               Source="{Binding NormalImage, RelativeSource={RelativeSource TemplatedParent}}" />
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed"
                                 Value="True">
                        <Setter TargetName="Image"
                                Property="Source"
                                Value="{Binding PressedImage, RelativeSource={RelativeSource TemplatedParent}}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>


但请注意,当您提出问题时,应始终提供问题的详细信息。

解决我的问题的方法是不允许按钮聚焦:

<Button Command="{Binding MyCommand}"
        Focusable="False"
        Content="Test"
        Width="100" />

对于WPF的ICommand来说,如果按钮在命令执行之前失去焦点,但如果按钮一开始就没有获得焦点,这似乎是个问题

我很幸运,这些按钮的功能是通过控件上的选项卡导航提供的,因此我不需要重构代码设置焦点。因为UI设计师不想在按钮上显示键盘焦点,所以在我的书中这是一个双赢的结果

我最初的一个问题是如何调试这个问题。我从来没有得到一个合适的答案,所以我将在下面总结我的过程:

  • 不要使用断点-这些断点会干扰调试鼠标交互
  • 添加
    Debug.WriteLine(“”)。这告诉了我哪些事件有效,哪些事件无效,以及顺序。这真的没用
  • 因为这是resent更改的结果,所以我逐个注释掉了最近的更改,直到我确定了导致问题的代码。这最终是对导致问题的组件的调用
  • 一旦我在我的更改中发现了有问题的代码行,我就取消了这一行并逐步完成了该调用。这使我使用Dispatcher找到了代码设置的焦点
  • 这一行非常可疑,因此我构建了一个模拟代码的示例项目,并验证了问题的根源就在这里

  • 也许这会对将来的人有所帮助。

    解决我的问题的方法是不允许按钮聚焦:

    <Button Command="{Binding MyCommand}"
            Focusable="False"
            Content="Test"
            Width="100" />
    
    
    
    对于WPF的ICommand来说,如果按钮在命令执行之前失去焦点,但如果按钮一开始就没有获得焦点,这似乎是个问题

    我很幸运,这些按钮的功能是通过控件上的选项卡导航提供的,因此我不需要重构代码设置焦点。因为UI设计师不想在按钮上显示键盘焦点,所以在我的书中这是一个双赢的结果

    我最初的一个问题是如何调试这个问题。我从来没有得到一个合适的答案,所以我将在下面总结我的过程:

  • 不要使用断点-这些断点会干扰调试鼠标交互
  • 添加
    Debug.WriteLine(“”)。这告诉了我哪些事件有效,哪些事件无效,以及顺序。这真的没用
  • 因为这是resent更改的结果,所以我逐个注释掉了最近的更改,直到我确定了导致问题的代码。这最终是对导致问题的组件的调用
  • 一旦我在我的更改中发现了有问题的代码行,我就取消了这一行并逐步完成了该调用。这使我使用Dispatcher找到了代码设置的焦点
  • 这一行非常可疑,因此我构建了一个模仿c语言的示例项目