将命令绑定到ToggleButton的Checked和Unchecked事件

16

我在我的C# WPF应用程序中有一个ToggleButton,我想将一个Command绑定到Checked事件,将另一个Command绑定到Unchecked事件。

我目前拥有的是以下内容:

<ToggleButton Name="btnOpenPort" Style="{StaticResource myOnOffBtnStyle}" Content="Open Port"
              Checked="btnOpenPort_Checked" Unchecked="btnOpenPort_Unchecked"
              IsChecked="{Binding Path=PortViewModel.PortIsOpen, Mode=OneWay}"
              Canvas.Left="75" Canvas.Top="80" Height="25" Width="100"/>
但这不是我想做的。因为在这种情况下,我必须在代码后台设置 Checked 和 Unchecked 事件的属性。 相反,我想在 ViewModel 中调用一个命令 (ICommand),一旦 Checked 或 Unchecked 事件被触发,这样我就不需要任何代码后台来控制我的切换按钮。
有没有办法直接在 XAML 中绑定这两个事件的命令? 类似于 WPF “标准”按钮控件的命令属性?
编辑 以下是@har07提示方案的工作方式:
1:如果您还没有引用,请添加引用:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"

2: 实现了Interaction.Triggers用于Checked和Unchecked事件:

<ToggleButton 
        Name="btnOpenPort" Style="{StaticResource myOnOffBtnStyle}" Content="Open Port"
        IsChecked="{Binding Path=PortViewModel.PortIsOpen, Mode=OneWay}"
        Canvas.Left="75" Canvas.Top="80" Height="25" Width="100">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Checked">
                <i:InvokeCommandAction Command="{Binding Path=PortViewModel.OpenPort}"/>
            </i:EventTrigger>
            <i:EventTrigger EventName="Unchecked">
                <i:InvokeCommandAction Command="{Binding Path=PortViewModel.ClosePort}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
</ToggleButton>
通过这个解决方案,我不需要更改ViewModel或代码后台中的任何一行代码。 我只需要调用我的ICommand,就像按照MVVM模式使用标准按钮一样。
4个回答

30

直接绑定两个命令到选中和取消选中事件可能不可行,但您仍然可以绑定一个命令,并且它将被同时调用。如果您需要不同的命令来处理这两个事件,还可以使用附加行为选项。

<ToggleButton Command="{Binding MyCommand}"/>

在虚拟机中

public ICommand MyCommand { get; private set; }

你需要相应地进行初始化

为了确定当前状态,您可以在绑定的属性PortIsOpen上设置条件。

void Execute(object state)
{
    if(PortIsOpen)
    {
        //checked
    }
    else
    {
        //unchecked
    }
}
或者你也可以将它作为参数传递。
例如。
<ToggleButton Command="{Binding MyCommand}" 
              CommandParameter="{Binding IsChecked,RelativeSource={RelativeSource Self}}"/>

并将其用作

void Execute(object state)
{
    if((bool)state)
    {
        //checked
    }
    else
    {
        //unchecked
    }
}

11

也许我们可以使用EventTriggers

    <ToggleButton>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Checked">
                <i:InvokeCommandAction Command="{Binding Path=CheckedCommand}"/>
            </i:EventTrigger>
            <i:EventTrigger EventName="Unchecked">
                <i:InvokeCommandAction Command="{Binding Path=UncheckedCommand}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </ToggleButton>

要使用触发器,我们需要引用System.Windows.Interactivity

 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

谢谢,这正是我所做的。@har07的链接恰好指向了这种方法。我几分钟前刚刚更新了我的帖子,采用了这种方法! - ck84vi
很高兴你解决了问题,抱歉,我不是故意重复发布的,我没有看到提供的链接。 - user3473830

7
您可以将处理选中/取消选中事件的逻辑放在 PortIsOpen 属性的 setter 中:
private bool _portIsOpen;
public bool PortIsOpen
{
    get { return _portIsOpen; }
    set
    {
        if(value) HandleCheckedEvent();
        else HandleUnCheckedEvent();
        ....
    }
}

或者您可以使用Interaction.Triggers扩展将事件绑定到命令: WPF绑定ViewModel中的UI事件到命令


我使用了Interaction.Triggers来实现它。这完美地运作了!正是我所需要的!非常感谢你! - ck84vi

-2
 <ToggleButton Name="btnOpenPort" Style="{StaticResource myOnOffBtnStyle}" Content="Open Port"
              Checked="{Binding ICommand}"  Unchecked="{Binding ICommand}"
              IsChecked="{Binding Path=PortViewModel.PortIsOpen, Mode=OneWay}"
              Canvas.Left="75" Canvas.Top="80" Height="25" Width="100"/>

将ICommand替换为您的ICommand属性名称。


1
这种方法会抛出一个XamlParseException异常 - “在'System.Windows.Data.Binding'上提供值引发了异常。”- 指向我绑定ICommand的那一行。_{"无法将类型为'System.Reflection.RuntimeEventInfo'的对象强制转换为类型'System.Reflection.MethodInfo'。"}_。 - ck84vi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接