Slex For Silverlight Preview 2 – Conditionally invoking Triggers & Actions, Decoupled Triggers, etc.
Couple of weeks back, I introduced the Slex Project. And thanks to the Christmas holidays; today I checked in the Preview 2 of Slex. Here are few cool features in Slex Preview 2. You can download the same here from CodePlex – http://slex.codeplex.com
What is there in Slex?
If you are familiar with Silverlight/Expression Blend, you should be knowing about the System.Windows.Interactions infrastructure – which provides various Behaviors, Triggers and Actions. Slex is an experimental implementation of some additional triggers and actions on top of the same, along with few extension points.
Triggers in Slex, and actions inside them, can be invoked based on conditions
These are some notable aspects in Slex, that are not available in the triggers and actions available with Expression Blend.
- Slex allows you to define multiple conditions for invoking triggers (like you can specify a KeyDown event trigger should be fired only if ‘A’ is pressed)
- You can specify multiple conditions for invoking each action in a trigger
- Slex introduces few more Triggers and Actions that you’ll see soon.
As of now, Slex Preview 2 Provides the following Triggers
- EventTrigger – Will be fired when an event is raised. Can listen to events of Elements, or events from your view model
- PropertyTrigger – Will be fired when the specified property changes. Can listen to properties of Elements, or property in your view model
- ReactiveTrigger – Can ‘import’ an Observable that you may ‘export’ using MEF. Useful to define and use custom events using System.Reactive.
And the following actions
- InvokeMethodAction – Invoke a method directly in the View model or for a target element, supports passing parameters via Xaml
- InvokeCommandAction – Invoke an ICommand in the view model
- StoryBoardAction – Start, Stop, Pause, Resume, or Reverse story boards
- PropertyAction – Sets a property value (very crude as of now)
You can specify one or more InvokingCondition for triggers and/or actions. Also, actions like InvokeMethodAction and InvokeCommandAction has an ActionParameters property, so that you can pass one or more Parameters when invoking methods and commands.
Conditionally Invoking Triggers and Actions
Let us see a simple example on a scenario – You need to start a story board when a button is pressed, but you need to do that only if a particular checkbox is checked. Assuming your Button is btnBegin, your StoryBoard is myStoryBoard and your checkbox is chkMain, this is something that you can do. (See the StoryBoardAction demo)
If you see the above code, you may find that we are specifying various conditions for the trigger itself – all Actions in the Trigger will fire only if all Invoking Conditions are True. You should be able to place other Actions (that comes with Expression Blend, you own custom actions etc) with in an EventTrigger, PropertyTrigger or ReactiveTrigger – to execute them conditionally.
Also, you may need to specify conditions for invoking each Action in the trigger individually. You can do this as well. For example, the following Property Trigger will execute only if the Text property of the Textbox txtData is Hello, and the checkbox myCheckBox is checked.
Better MVVM - Invoking Methods and Commands in your View Model and Passing parameters
Have a look at the InvokeMethodAction and InvokeCommandAction (see the demo). There are some changes for these actions from Preview 1.
InvokeCommandAction let you invoke a method against the view model. Assume that you’ve a list box named userList - here is a simple example on how to execute a command when ever the selection is changed, and you can specify a parameter for your ICommand using the ActionParameter. In fact, you can pass more than one ActionParameter – and in that case, they will be passed as an object array to the CanExecute and Execute methods in your command.
And here is something more interesting - InvokeMethodAction. You can use InvokeMethodAction to invoke methods in your view model directly. Assume that you have a UI with two text boxes and a button, and you’ve an Add method in your view model that takes two arguments of type integer. This is what you need to do to invoke your Add method, when the user clicks the button btnName.
ReactiveTrigger – Decoupling Triggers with the help of MEF and System.Reactive
One interesting addition in this preview is the ReactiveTrigger. ReactiveTrigger let you import an Observable you exported from some where else. This will let you create customized user input triggers pretty quickly. I’m not going to the implementation details, but assuming you are already familiar a bit with MEF concepts and System.Reactive concepts, here is what you can do (See ReactiveTrigger demo in the Slex.Lib.Demo for entire source code)
Step 1 – Some where in your host application, Create a trigger and export it
Your exported method should match the signature Func<object,IObservable<EventResult>>. You can use the ObservableExport attribute in Slex.Lib to mark your trigger as an exportable part. Also, the name you provide to the ExportName attribute will be later used in Xaml to ‘import’ this trigger.
Step 2 – In your application startup, call Compose method in SlexPartComposer, and pass your catalogs
In this case I’m simply passing and assembly catalog with the current assembly, because I’ve my trigger as part of my host app. And I’ve this line in the App.xaml.cs constructor.
Step 3 – Just use the trigger in your Xaml
Here we go, you can import the exported trigger, and this will get fired when ever a key is pressed.
Using Slex with Blend
You should be able to use Blend to modify most Slex triggers and actions. For example, let us see how the above Event Trigger and related action parameters will look like in Blend. You may find that you can modify the Conditions and Parameters of a trigger from with in Blend (Well, they are AttachableCollections to be precise :)).
How Slex relates to the already available Behaviors, Triggers, and actions that comes with Expression Blend?
As mentioned earlier, Slex is built on top of System.Windows.Interactions infrastructure, and you will be able to use mix and match existing Expression Blend behaviors, triggers and actions along with Slex triggers and actions.
There are few overlapping areas – For example, Slex has its own implementation for some triggers like EventTrigger, that provides some ‘extra’ features when compared to Blend’s EventTrigger.
Slex is very much in a preview stage, and I’ll continue hacking on this with respect to my time.