I'm using Microsoft Expression Blend 4
I have a Browser ..,
[ XAML ] ConnectionView " Empty Code Behind "
<WebBrowser local:AttachedProperties.BrowserSource="{Binding Source}">
<i:Interaction.Triggers>
<i:EventTrigger>
<i:InvokeCommandAction Command="{Binding LoadedEvent}"/>
</i:EventTrigger>
<i:EventTrigger EventName="Navigated">
<i:InvokeCommandAction Command="{Binding NavigatedEvent}" CommandParameter="??????"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</WebBrowser>
[ C# ] AttachedProperties class
public static class AttachedProperties
{
public static readonly DependencyProperty BrowserSourceProperty = DependencyProperty . RegisterAttached ( "BrowserSource" , typeof ( string ) , typeof ( AttachedProperties ) , new UIPropertyMetadata ( null , BrowserSourcePropertyChanged ) );
public static string GetBrowserSource ( DependencyObject _DependencyObject )
{
return ( string ) _DependencyObject . GetValue ( BrowserSourceProperty );
}
public static void SetBrowserSource ( DependencyObject _DependencyObject , string Value )
{
_DependencyObject . SetValue ( BrowserSourceProperty , Value );
}
public static void BrowserSourcePropertyChanged ( DependencyObject _DependencyObject , DependencyPropertyChangedEventArgs _DependencyPropertyChangedEventArgs )
{
WebBrowser _WebBrowser = _DependencyObject as WebBrowser;
if ( _WebBrowser != null )
{
string URL = _DependencyPropertyChangedEventArgs . NewValue as string;
_WebBrowser . Source = URL != null ? new Uri ( URL ) : null;
}
}
}
[ C# ] ConnectionViewModel Class
public class ConnectionViewModel : ViewModelBase
{
public string Source
{
get { return Get<string> ( "Source" ); }
set { Set ( "Source" , value ); }
}
public void Execute_ExitCommand ( )
{
Application . Current . Shutdown ( );
}
public void Execute_LoadedEvent ( )
{
MessageBox . Show ( "___Execute_LoadedEvent___" );
Source = ...... ;
}
public void Execute_NavigatedEvent ( )
{
MessageBox . Show ( "___Execute_NavigatedEvent___" );
}
}
[ C# ] ViewModelBase class Here
Finally :
Binding with commands works well and MessageBoxes shown
My Question :
How to pass NavigationEventArgs as Command Parameters when Navigated Event occurs ?
What I do is to use InvokeCommandAction to bind the control loaded event to a command in the view model, give the control a x:Name in Xaml and pass as CommandParameter, then in said loaded command hook view model handlers up to the events where I need to get the event args.
I try to keep my dependencies to a minimum, so I implemented this myself instead of going with EventToCommand of MVVMLight. Works for me so far, but feedback is welcome.
Xaml:
ViewModel:
EventToCommandBehavior:
ActionCommand:
I don't think you can do that easily with the
InvokeCommandAction
- I would take a look atEventToCommand
from MVVMLight or similar.I know this is a fairly old question, but I ran into the same problem today and wasn't too interested in referencing all of MVVMLight just so I can use event triggers with event args. I have used MVVMLight in the past and it's a great framework, but I just don't want to use it for my projects any more.
What I did to resolve this problem was create an ULTRA minimal, EXTREMELY adaptable custom trigger action that would allow me to bind to the command and provide an event args converter to pass on the args to the command's CanExecute and Execute functions. You don't want to pass the event args verbatim, as that would result in view layer types being sent to the view model layer (which should never happen in MVVM).
Here is the EventCommandExecuter class I came up with:
This class has two dependency properties, one to allow binding to your view model's command, the other allows you to bind the source of the event if you need it during event args conversion. You can also provide culture settings if you need to (they default to the current UI culture).
This class allows you to adapt the event args so that they may be consumed by your view model's command logic. However, if you want to just pass the event args on verbatim, simply don't specify an event args converter.
The simplest usage of this trigger action in XAML is as follows:
If you needed access to the source of the event, you would bind to the owner of the event
(this assumes that the XAML node you're attaching the triggers to has been assigned
x:Name="SomeEventSource"
This XAML relies on importing some required namespaces
and creating an
IValueConverter
(calledNameChangedArgsToStringConverter
in this case) to handle the actual conversion logic. For basic converters I usually create a defaultstatic readonly
converter instance, which I can then reference directly in XAML as I have done above.The benefit of this solution is that you really only need to add a single class to any project to use the interaction framework much the same way that you would use it with
InvokeCommandAction
. Adding a single class (of about 75 lines) should be much more preferable to an entire library to accomplish identical results.NOTE
this is somewhat similar to the answer from @adabyron but it uses event triggers instead of behaviours. This solution also provides an event args conversion ability, not that @adabyron's solution could not do this as well. I really don't have any good reason why I prefer triggers to behaviours, just a personal choice. IMO either strategy is a reasonable choice.
Here is a version of @adabyron's answer that prevents the leaky
EventArgs
abstraction.First, the modified
EventToCommandBehavior
class (now a generic abstract class and formatted with ReSharper code cleanup). Note the newGetCommandParameter
virtual method and its default implementation:Next, an example derived class that hides
DragCompletedEventArgs
. Some people expressed concern about leaking theEventArgs
abstraction into their view model assembly. To prevent this, I created an interface that represents the values we care about. The interface can live in the view model assembly with the private implementation in the UI assembly:Cast the command parameter to
IDragCompletedArgs
, similar to @adabyron's answer.It's not easily supported. Here's an article with instructions on how to pass EventArgs as command parameters.
You might want to look into using MVVMLight - it supports EventArgs in command directly; your situation would look something like this: