在wpf中有什么优雅的方法来处理命令和单击事件吗?

本文关键字:命令 处理 单击 事件 方法 wpf 什么 | 更新日期: 2023-09-27 18:06:12

我在WPF应用程序中有一个自定义控件,它有一个Apply按钮。当用户单击按钮时,我想在我的视图模型(业务逻辑)上执行命令,但我也想为用户界面执行一些事件。

在我看来,如果我使用Command属性,我不能使用Click事件处理程序。但是,我真的不想把我的逻辑混在一起(一些逻辑是业务逻辑,一些是UI逻辑)。

现在,我决定从后面的代码调用ICommand.Execute方法并使用Click事件。这样做的问题是现在我不能利用ICommand.CanExecute方法。

public class OrderViewModel : ViewModelBase
{
    public DelegateCommand ProcessCommand { get; private set; }
    public void Process(object parameter)
    {
        // Business logic here...
    }
}
<Button Click="OnProcess_Click" />
public void OnProcess_Click(object sender, RoutedEventArgs e)
{
    ViewModel.ProcessCommand.Execute();
    // Do UI specific stuff...
}

我觉得我这样做很糟糕,特别是因为我失去了整个ICommand.CanExecute的好处,但我不确定我还能做什么。

更新:我认为值得一提的是,我更喜欢我希望我的命令在UI逻辑之前执行,不确定这是否会改变事情。

在wpf中有什么优雅的方法来处理命令和单击事件吗?

您可以使用System.Windows.Interactivity.InvokeCommandAction来调用您的ProccessCommand:

 <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <i:InvokeCommandAction Command="{Binding DataContext.ProcessCommand}" />
        </i:EventTrigger>
  </i:Interaction.Triggers>

您可以将Button的Command属性绑定到视图中的命令,它执行与当前事件处理程序相同的逻辑。从中受益的是,可以定义切换按钮启用状态的CanExecute。这样你就可以从ViewModel的命令中传播CanExecute逻辑。例如:

你可以在你的根控制上有一个命令:

<Button Command="{Binding ProcessCommand, ElementName=root, Mode=OneWay}" />

上面的代码片段适用于具有x:Name="root"的控件,但是您可以随意命名它。或者,您可以选择另一种导航到根控件的方式,在代码后端定义视图命令。命令可以如下所示:

    private ICommand _processCommand;
    public ICommand ProcessCommand
    {
        get { return _processCommand ?? (_processCommand = new DelegateCommand(Process, CanProcess)); }
    }
    private bool CanProcess(object obj)
    {
        return ViewModel.ProcessCommand.CanExecute(obj);
    }
    private void Process(object obj)
    {
        ViewModel.ProcessCommand.Execute(obj);
        // Do UI specific stuff...
    }

通过这种方式,您可以重用ViewModel命令的全部功能,并能够以您想要的方式扩展它。执行顺序也是有保证的。