Nie ma wbudowanego sposobu, więc oto jak to zrobić:
Klasyczny Interakcje wyzwalania służy tak:
<Button Content="I am a button">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding CommandWithNoArgs}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Nie możemy uzyskać dostęp do EventArgs
z MouseEnter
wydarzenie przez wiązanie, więc będziemy musieli zmodyfikować fragment, który go wyrzuci.
Tak się składa, że ten kawałek to InvokeCommandAction
.
"Więc zamierzamy ją podklasować i zastąpić wygodną metodę, która czekała na nas cały czas" jest tym, co chciałbym napisać. Ale klasa jest zapieczętowana.
Więc będziemy mieć do podklasy jego rodzica (streszczenie) Klasa: TriggerAction<DependencyObject>
Najprostsza implementacja jest:
public class InteractiveCommand : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
}
}
I parameter
to EventArgs
!
Ale trzymaj się, to nie jest takie proste, musimy odtworzyć zachowanie zwykłego InvokeCommandAction
.
Przez Reflector, ja ją dekompilowałem (ale mógłbyś spojrzeć na oficjalne źródło, jestem po prostu leniwy).
Nie będziemy się przejmować własnością zależną CommandParameter
, zakładamy, że jeśli użyjesz tego zamiast InvokeCommandAction
, za każdym razem będziesz potrzebować EventArgs
.
Tu idzie pełną klasę (tylko WPF, zobacz EDIT dla Silverlight):
public class InteractiveCommand : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
if (base.AssociatedObject != null)
{
ICommand command = this.ResolveCommand();
if ((command != null) && command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
}
private ICommand ResolveCommand()
{
ICommand command = null;
if (this.Command != null)
{
return this.Command;
}
if (base.AssociatedObject != null)
{
foreach (PropertyInfo info in base.AssociatedObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (typeof(ICommand).IsAssignableFrom(info.PropertyType) && string.Equals(info.Name, this.CommandName, StringComparison.Ordinal))
{
command = (ICommand)info.GetValue(base.AssociatedObject, null);
}
}
}
return command;
}
private string commandName;
public string CommandName
{
get
{
base.ReadPreamble();
return this.commandName;
}
set
{
if (this.CommandName != value)
{
base.WritePreamble();
this.commandName = value;
base.WritePostscript();
}
}
}
#region Command
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
// Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(InteractiveCommand), new UIPropertyMetadata(null));
#endregion
}
Jak w przypadku każdego kodu pobieramy z internetu, Gorąco polecam przeczytanie całej klasy, i stara się zrozumieć co robi. Nie wrzucaj go do swojej aplikacji.
Teraz możemy zrobić:
<Button Content="I am a button">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<local:InteractiveCommand Command="{Binding CommandWithEventArgs}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
i kodeksem tyle:
#region CommandWithEventArgs
DelegateCommand<MouseEventArgs> _CommandWithEventArgs;
/// <summary>
/// Exposes <see cref="CommandWithEventArgs(MouseEventArgs)"/>.
/// </summary>
public DelegateCommand<MouseEventArgs> CommandWithEventArgs
{
get { return _CommandWithEventArgs ?? (_CommandWithEventArgs = new DelegateCommand<MouseEventArgs>(CommandWithEventArgs)); }
}
#endregion
public void CommandWithEventArgs(MouseEventArgs param)
{
}
a to wrap;)
EDIT: dla Silverlight, użyj tego kodu:
public class InteractiveCommand : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
if (base.AssociatedObject != null)
{
ICommand command = Command;
if ((command != null) && command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
}
#region Command
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
// Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(InteractiveCommand), new UIPropertyMetadata(null));
#endregion
}
Należy jednak pamiętać, że jest mniej bezpieczny niż w przypadku pełnej wersji WPF (nie sprawdza typów, może ulec awarii przy zamrożonych elementach).
Nie umieszczaj tagów w tytule pytania. Zobacz [ten link] (http://meta.stackexchange.com/questions/10647/how-do-i-write-a-good-title) na pisanie dobrych tytułów;) –