我有一个树视图。使用代码隐藏方法处理事件TreeViewItem.Expanded
时treeView_Expanded(object sender, RoutedEventArgs e)
有两个参数:
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;
}
但是,当我使用 MVVM 规则处理TreeViewItem.Expanded
事件时,我总是采用第一个参数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 中处理事件时如何发送第二个参数?
您可以使用另一个 TriggerAction 在 VM 中调用命令,该命令也将传递参数:
<TreeView ItemsSource="{Binding Person}">
<i:Interaction.Triggers>
<helper:RoutedEventTrigger RoutedEvent="TreeViewItem.Expanded">
<local:CustomCommandAction Command="{Binding GetNewTreeViewItemCommand}"/>
</helper:RoutedEventTrigger>
</i:Interaction.Triggers>
自定义命令操作
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>
虚拟机
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);
}
}
路由事件触发器
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;
}
}
自定义命令操作
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));
}
}
}
}
}
}