C#如何处理在 MVVM 事件时发送的事件处理程序的第二个参数?

标签: MVVM WPF xaml C#
发布时间: 2017/2/24 1:08:40
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

我有树视图。有两个参数 treeView_Expanded(object sender, RoutedEventArgs e) 当事件 TreeViewItem.Expanded 使用代码隐藏方法处理︰

XAML:

<TreeView Name="treeView" TreeViewItem.Expanded="treeView_Expanded"/> 

代码隐藏︰

private void treeView_Expanded(object sender, RoutedEventArgs e)
{ 
     //***I take THE SECOND PARAMETER to work ***
     TreeViewItem item = e.Source as TreeViewItem;

}

然而,当我正在处理 TreeViewItem.Expanded 事件使用 MVVM 规则,我总是采取的第一个参数 object sender 。但我想要第二个参数 RoutedEventArgs e :

XAML:

<TreeView ItemsSource="{Binding Person}">
   <i:Interaction.Triggers>
      <helper:RoutedEventTrigger RoutedEvent="TreeViewItem.Expanded">
         <prism:InvokeCommandAction Command="{Binding GetNewTreeViewItemCommand}"/>
      </helper:RoutedEventTrigger>
   </i:Interaction.Triggers>
</TreeView>

视图模型︰

public DelegateCommand<RoutedEventArgs> GetNewTreeViewItemCommand { get; set; }
public MainWindowViewModel()
{
   GetNewTreeViewItemCommand = new DelegateCommand<RoutedEventArgs>(LoadNewTreeViewITem);
}

private void LoadNewTreeViewITem(RoutedEventArgs e)
{
   //e is "object sender"(the FIRST parameter), but I want to take  
   //RoutedEventArgs e(the SECOND parameter)             
}           

如何可以处理在 MVVM 事件时发送第二个参数?

解决方法 1:

您可以使用另一个 TriggerAction 来在您的 VM,将传递参数以及调用命令︰

<TreeView ItemsSource="{Binding Person}">
  <i:Interaction.Triggers>
     <helper:RoutedEventTrigger RoutedEvent="TreeViewItem.Expanded">
        <local:CustomCommandAction Command="{Binding GetNewTreeViewItemCommand}"/>
     </helper:RoutedEventTrigger>
  </i:Interaction.Triggers>

CustomCommandAction

public sealed class CustomCommandAction : TriggerAction<DependencyObject>
{
    public static readonly DependencyProperty CommandParameterProperty =
        DependencyProperty.Register("CommandParameter", typeof(object), typeof(CustomCommandAction), null);

    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
        "Command", typeof(ICommand), typeof(CustomCommandAction), null);

    public ICommand Command
    {
        get
        {
            return (ICommand)this.GetValue(CommandProperty);
        }
        set
        {
            this.SetValue(CommandProperty, value);
        }
    }

    public object CommandParameter
    {
        get
        {
            return this.GetValue(CommandParameterProperty);
        }

        set
        {
            this.SetValue(CommandParameterProperty, value);
        }
    }

    protected override void Invoke(object parameter)
    {
        if (this.AssociatedObject != null)
        {
            ICommand command = this.Command;
            if (command != null)
            {
                if (this.CommandParameter != null)
                {
                    if (command.CanExecute(this.CommandParameter))
                    {
                        command.Execute(this.CommandParameter);
                    }
                }
                else
                {
                    if (command.CanExecute(parameter))
                    {
                        command.Execute(parameter);
                    }
                }
            }
        }
    }
}

更新

XAML

    <TreeView ItemsSource="{Binding Person}" Grid.Row="1" >
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Description}" />
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
        <i:Interaction.Triggers>
            <local:RoutedEventTrigger RoutedEvent="TreeViewItem.Expanded">
                <local:CustomCommandAction Command="{Binding GetNewTreeViewItemCommand}"/>
            </local:RoutedEventTrigger>
        </i:Interaction.Triggers>
    </TreeView>

VM

    private ObservableCollection<Person> _people = new ObservableCollection<Person>();

    public ObservableCollection<Person> Person
    {
        get { return _people; }
    }


    private DelegateCommand _getNewTreeViewItemCommand = null;

    public ICommand GetNewTreeViewItemCommand { get { return _getNewTreeViewItemCommand; } }


    private void LoadNewTreeViewITem(object param)
    {
        var tuple = (Tuple<object, object>)param;

        object sender = tuple.Item1;
        RoutedEventArgs e = tuple.Item2 as RoutedEventArgs;

        System.Diagnostics.Debug.WriteLine(sender);
        System.Diagnostics.Debug.WriteLine(e.RoutedEvent);
    }

    public MainWindowViewModel()
    {
        _getNewTreeViewItemCommand = new DelegateCommand(LoadNewTreeViewITem, (o) => true);

        for (int i = 0; i < 10; i++)
        {
            var newPerson = new Person() { Description = i.ToString() };
            for (int j = 0; j < 10; j++)
            {
                newCode.Children.Add(new Person() { Description = i.ToString() + j.ToString() });
            }

            _people.Add(newCode);
        }
    }

public class Person
{
    public string Description { get; set; }

    public ObservableCollection<Person> Children { get; set; } = new ObservableCollection<Person>();
}

命令

public class DelegateCommand : ICommand
{
    private readonly Action<object> _execute;
    private readonly Func<object, bool> _canExecute;

    public event EventHandler CanExecuteChanged;


    public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

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

    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}

RoutedEventTrigger

public class RoutedEventTrigger : EventTriggerBase<DependencyObject>
{
    RoutedEvent _routedEvent;

    public RoutedEvent RoutedEvent
    {
        get { return _routedEvent; }
        set { _routedEvent = value; }
    }

    public RoutedEventTrigger()
    {
    }
    protected override void OnAttached()
    {
        Behavior behavior = base.AssociatedObject as Behavior;
        FrameworkElement associatedElement = base.AssociatedObject as FrameworkElement;

        if (behavior != null)
        {
            associatedElement = ((IAttachedObject)behavior).AssociatedObject as FrameworkElement;
        }
        if (associatedElement == null)
        {
            throw new ArgumentException("Routed Event trigger can only be associated to framework elements");
        }
        if (RoutedEvent != null)
        {
            associatedElement.AddHandler(RoutedEvent, new RoutedEventHandler(this.OnRoutedEvent));
        }
    }
    void OnRoutedEvent(object sender, RoutedEventArgs args)
    {
        base.OnEvent(args);
    }
    protected override string GetEventName()
    {
        return RoutedEvent.Name;
    }
}

CustomCommandAction

public sealed class CustomCommandAction : TriggerAction<DependencyObject>
{
    public static readonly DependencyProperty CommandParameterProperty =
        DependencyProperty.Register("CommandParameter", typeof(object), typeof(CustomCommandAction), null);

    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
        "Command", typeof(ICommand), typeof(CustomCommandAction), null);

    public ICommand Command
    {
        get
        {
            return (ICommand)this.GetValue(CommandProperty);
        }
        set
        {
            this.SetValue(CommandProperty, value);
        }
    }

    public object CommandParameter
    {
        get
        {
            return this.GetValue(CommandParameterProperty);
        }

        set
        {
            this.SetValue(CommandParameterProperty, value);
        }
    }

    protected override void Invoke(object parameter)
    {
        if (this.AssociatedObject != null)
        {
            ICommand command = this.Command;
            if (command != null)
            {
                if (this.CommandParameter != null)
                {
                    if (command.CanExecute(this.CommandParameter))
                    {
                        command.Execute(this.CommandParameter);
                    }
                }
                else
                {
                    if (command.CanExecute(parameter))
                    {
                        command.Execute(new Tuple<object, object>(this.AssociatedObject, parameter));
                    }
                }
            }
        }
    }
}
赞助商