c# - 如何将 ICommand 添加到 FrameworkElement 中的事件?

标签 c# xaml mvvm

如何将 ICommand 添加到 FrameworkElement 中的事件?

具体来说,我想做以下事情

<ListView> <!-- Button, Windows or whatever element -->
    <my:EventToCommand 
        Name="PreviewMouseLeftButton"
        Command="{Binding Path=MyCommand}"
        CommandParameter="{Binding ...}" />
    <!-- Value, Element, etc.. -->
</ListView>

我想实现自己的解决方案,用于教育目的,我不想使用任何第三方库(MVVM Light、Prism 等)

最佳答案

您需要使用附加行为。为了演示目的,假设我想使用 MVVM 和 ICommand 模式实现按钮双击,以下是相关代码:

首先,创建一个名为 ButtonBehaviors 的静态类,如下所示:

public static class ButtonBehaviors
{
    public static object GetButtonDoubleClick(DependencyObject obj)
    {
        return obj.GetValue(ButtonDoubleClickProperty);
    }

    public static void SetButtonDoubleClick(DependencyObject obj, object value)
    {
        obj.SetValue(ButtonDoubleClickProperty, value);
    }

    public static readonly DependencyProperty ButtonDoubleClickProperty =
        DependencyProperty.RegisterAttached("ButtonDoubleClick", typeof (object), typeof (ButtonBehaviors),
                                            new UIPropertyMetadata(new PropertyChangedCallback(OnButtonDoubleClickChanged)));

    private static void OnButtonDoubleClickChanged (DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var button = d as Button;
        if(button == null)
        {
            return;
        }

        var command = e.NewValue as ICommand;
        if(command == null)
        {
            return;
        }

        button.MouseDoubleClick += (o, ev) => command.Execute(button);
    }
}

(我稍后会解释)

然后,您将如何使用它:

MainWindow.xaml:

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfApplication3="clr-namespace:WpfApplication3" Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="Button" 
                Height="23" 
                HorizontalAlignment="Left" 
                Margin="173,89,0,0" 
                VerticalAlignment="Top" 
                WpfApplication3:ButtonBehaviors.ButtonDoubleClick="{Binding ButtonDoubleClick}"
                Width="75" />
    </Grid>
</Window>

最后,ViewModel:

public class ViewModel
{
    private ICommand _buttonDoubeClick;

    public ICommand ButtonDoubleClick
    {
        get
        {
            if (_buttonDoubeClick == null)
            {
                _buttonDoubeClick = new SimpleDelegateCommand(() => MessageBox.Show("Double click!!"));
            }

            return _buttonDoubeClick;
        }
    }
}

为了完整起见,既然你说没有第三方 dll,这里是我的 SimpleDelegateCommand:

public class SimpleDelegateCommand : ICommand
{
    private readonly Action _action;

    public SimpleDelegateCommand(Action action)
    {
        _action = action;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        if(_action != null)
        {
            _action();
        }
    }
}

简而言之,发生的事情是这样的:当您将 Command 分配给附加属性时,会引发 OnButtonDoubleClickChanged 事件,此时我们会挂接到 button.MouseDoubleClick 事件。

关于c# - 如何将 ICommand 添加到 FrameworkElement 中的事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11651745/

相关文章:

c# - 在 mvc core 2.1.3 API 中使用 FormatFilter 属性

c# - WPF 标签上的外发光效果和旋转

wpf - 带有MS SQL Server的通用Windows应用

javascript - 如何计算我创建的对象数量?

c# - 如何在 Web API 请求的 FromBody ViewModel 中使用具有 EnumMember 属性的枚举?

c# - 在 WPF XAML 窗口上添加图标会导致错误/崩溃 VS2012

extjs - 如何将GeoExt3添加到Extjs 6 MVVM体系结构?

WPF Combo Box 获取和设置数据

c# - 选择进入解释/临时表

c# - WPF 切换 UIElements 在 DataTemplate 中的可见性