Wpf MVVM中事件的一种好方法

Wpf MVVM中事件的一种好方法,wpf,events,mvvm,command,Wpf,Events,Mvvm,Command,所以我在尝试实现MVVM时遇到了这个问题。AFAIK在ViewModel类中执行方法的最佳方式是通过CommandBinding <Button Command={Binding DoSomethingCommand} /> 只是这次我需要双击ListBoxItem,而ListBoxItem没有实现ICommandSource。所以我想知道什么是最好的方法,如果有的话 谢谢 编辑: 我刚想了一个办法,但似乎有点老套。如果我公开ListBox.DoubleClick事件,并且我的

所以我在尝试实现MVVM时遇到了这个问题。AFAIK在ViewModel类中执行方法的最佳方式是通过CommandBinding

<Button Command={Binding DoSomethingCommand} />

只是这次我需要双击ListBoxItem,而ListBoxItem没有实现ICommandSource。所以我想知道什么是最好的方法,如果有的话

谢谢

编辑:


我刚想了一个办法,但似乎有点老套。如果我公开ListBox.DoubleClick事件,并且我的ViewModel类订阅该事件,并在触发DoubleClick时运行正确的方法,该怎么办?

您可以使用附加的行为


请参见此处:

您可以使用附加的行为


请参见此处:

Silverlight不包含像WPF中的按钮那样的命令按钮。我们解决这个问题的方法是创建一个包含命令的自定义控件,并将该事件映射到该命令。这样的办法应该行得通

public class CommandListBoxItem : ListBoxItem
{
    public CommandListBoxItem()
    {
        DoubleClick += (sender, e) =>
        {
            if (Command != null && Command.CanExecute(CommandParameter))
                Command.Execute(CommandParameter);
        };
    }

    #region Bindable Command Properties

    public static DependencyProperty DoubleClickCommandProperty =
        DependencyProperty.Register("DoubleClickCommand",
                                    typeof(ICommand), typeof(CommandListBoxItem),
                                    new PropertyMetadata(null, DoubleClickCommandChanged));

    private static void DoubleClickCommandChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
    {
        var item = source as CommandListBoxItem;
        if (item == null) return;

        item.RegisterCommand(args.OldValue as ICommand, args.NewValue as ICommand);
    }

    public ICommand DoubleClickCommand
    {
        get { return GetValue(DoubleClickCommandProperty) as ICommand; }
        set { SetValue(DoubleClickCommandProperty, value); }
    }

    public static DependencyProperty DoubleClickCommandParameterProperty =
        DependencyProperty.Register("DoubleClickCommandParameter",
                                    typeof(object), typeof(CommandListBoxItem),
                                    new PropertyMetadata(null));

    public object DoubleClickCommandParameter
    {
        get { return GetValue(DoubleClickCommandParameterProperty); }
        set { SetValue(DoubleClickCommandParameterProperty, value); }
    } 

    #endregion

    private void RegisterCommand(ICommand oldCommand, ICommand newCommand)
    {
        if (oldCommand != null)
            oldCommand.CanExecuteChanged -= HandleCanExecuteChanged;

        if (newCommand != null)
            newCommand.CanExecuteChanged += HandleCanExecuteChanged;

        HandleCanExecuteChanged(newCommand, EventArgs.Empty);
    }

    private void HandleCanExecuteChanged(object sender, EventArgs args)
    {
        if (DoubleClickCommand != null)
            IsEnabled = DoubleClickCommand.CanExecute(DoubleClickCommandParameter);
    }      
}
然后,在创建ListBoxItems时,绑定到新的命令属性

<local:CommandListBoxItem DoubleClickCommand="{Binding ItemDoubleClickedCommand}" />

Silverlight没有像WPF中的按钮那样包含命令按钮。我们解决这个问题的方法是创建一个包含命令的自定义控件,并将该事件映射到该命令。这样的办法应该行得通

public class CommandListBoxItem : ListBoxItem
{
    public CommandListBoxItem()
    {
        DoubleClick += (sender, e) =>
        {
            if (Command != null && Command.CanExecute(CommandParameter))
                Command.Execute(CommandParameter);
        };
    }

    #region Bindable Command Properties

    public static DependencyProperty DoubleClickCommandProperty =
        DependencyProperty.Register("DoubleClickCommand",
                                    typeof(ICommand), typeof(CommandListBoxItem),
                                    new PropertyMetadata(null, DoubleClickCommandChanged));

    private static void DoubleClickCommandChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
    {
        var item = source as CommandListBoxItem;
        if (item == null) return;

        item.RegisterCommand(args.OldValue as ICommand, args.NewValue as ICommand);
    }

    public ICommand DoubleClickCommand
    {
        get { return GetValue(DoubleClickCommandProperty) as ICommand; }
        set { SetValue(DoubleClickCommandProperty, value); }
    }

    public static DependencyProperty DoubleClickCommandParameterProperty =
        DependencyProperty.Register("DoubleClickCommandParameter",
                                    typeof(object), typeof(CommandListBoxItem),
                                    new PropertyMetadata(null));

    public object DoubleClickCommandParameter
    {
        get { return GetValue(DoubleClickCommandParameterProperty); }
        set { SetValue(DoubleClickCommandParameterProperty, value); }
    } 

    #endregion

    private void RegisterCommand(ICommand oldCommand, ICommand newCommand)
    {
        if (oldCommand != null)
            oldCommand.CanExecuteChanged -= HandleCanExecuteChanged;

        if (newCommand != null)
            newCommand.CanExecuteChanged += HandleCanExecuteChanged;

        HandleCanExecuteChanged(newCommand, EventArgs.Empty);
    }

    private void HandleCanExecuteChanged(object sender, EventArgs args)
    {
        if (DoubleClickCommand != null)
            IsEnabled = DoubleClickCommand.CanExecute(DoubleClickCommandParameter);
    }      
}
然后,在创建ListBoxItems时,绑定到新的命令属性

<local:CommandListBoxItem DoubleClickCommand="{Binding ItemDoubleClickedCommand}" />

您可以在代码隐藏文件中处理事件,并调用ViewModel对象上的方法。在我看来,这比开始破解要好得多。:-)我不会将WPF路由事件传递给ViewModel对象


谁说暗号是被禁止的?模型-视图-视图-模型模式绝对不是。

您可以在代码隐藏文件中处理事件,并调用ViewModel对象上的方法。在我看来,这比开始破解要好得多。:-)我不会将WPF路由事件传递给ViewModel对象


谁说暗号是被禁止的?“模型视图”“视图”“模型模式”绝对不是。

这个示例似乎有点广泛,我回家后会给大家一个机会,并给出反馈。谢谢你的建议!这个例子似乎有点广泛,我回家后会给你一个机会,我会给你反馈。谢谢你的建议!