Windows 8 XAML Tips - Conditional Behaviors

By Fons Sonnemans, posted on
4096 Views 2 Comments

A few weeks ago I have written a blog post about how you can write your own Behaviors and Actions for Windows 8.1. I noticed that the Windows 8.1 Actions are not compatible with the Silverlight and Windows Phone Actions. Those actions have a IsEnabled property.

The Windows 8.1 Actions don't have an IsEnabled property.

Luckily I got a tip from the Microsoft XAML Tools team. A new feature that is added to the Behaviors SDK is that Actions can return results as well as have its own ActionLists. This helps in relaying execution results or building conditional behaviors. 

IsEnabledCondition

A have written a simple class called IsEnabledCondition. This class implements the IAction interface which makes it an Action. It has two dependency properties: IsEnabled and Actions. The Actions property is set as the ContentProperty using the ContentPropertyAttribute on the class. The Execute() method only executes the contained actions when the IsEnabled property is set. I learned this ActionList from reading Mark Smith Behaviors in Windows 8.1 Store Apps blog post.

using System;
using Microsoft.Xaml.Interactivity;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Markup;

namespace ConditionalBehaviorsDemo.Behaviors {

    [ContentProperty(Name = "Actions")]
    public class IsEnabledCondition : DependencyObject, IAction {


        #region IsEnabled Dependency Property

        /// <summary> 
        /// Get or Sets the IsEnabled dependency property.  
        /// </summary> 
        public bool IsEnabled {
            get { return (bool)GetValue(IsEnabledProperty); }
            set { SetValue(IsEnabledProperty, value); }
        }

        /// <summary> 
        /// Identifies the IsEnabled dependency property. 
        /// This enables animation, styling, binding, etc...
        /// </summary> 
        public static readonly DependencyProperty IsEnabledProperty =
            DependencyProperty.Register("IsEnabled",
                                        typeof(bool),
                                        typeof(IsEnabledCondition),
                                        new PropertyMetadata(true));

        #endregion IsEnabled Dependency Property

        #region Actions Dependency Property

        /// <summary>
        /// Actions collection
        /// </summary>
        public ActionCollection Actions {
            get {
                var actions = (ActionCollection)base.GetValue(ActionsProperty);
                if (actions == null) {
                    actions = new ActionCollection();
                    base.SetValue(ActionsProperty, actions);
                }
                return actions;
            }
        }

        /// <summary>
        /// Backing storage for Actions collection
        /// </summary>
        public static readonly DependencyProperty ActionsProperty =
            DependencyProperty.Register("Actions", 
                                        typeof(ActionCollection), 
                                        typeof(IsEnabledCondition), 
                                        new PropertyMetadata(null));

        #endregion Actions Dependency Property

        public object Execute(object sender, object parameter) {
            if (this.IsEnabled) {
                return Interaction.ExecuteActions(sender, this.Actions, parameter);
            }
            return null;
        }
    }
}

I use this action as the parent of my previously used ControlStoryBoardAction. The IsEnabled property is databound to the IsOn property of the ToggleSwitch. Databinding is possible because the IsEnabled property is an Dependency Property. If you start the application you can click the button it moves to the right and then comes back. If you turn the 'Animate' switch Off an then click the button nothing happens.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Button x:Name="button"
            Content="Button"
            HorizontalAlignment="Left"
            Height="97"
            Margin="90,72,0,0"
            VerticalAlignment="Top"
            Width="194"
            RenderTransformOrigin="0.5,0.5">
        <Button.RenderTransform>
            <CompositeTransform />
        </Button.RenderTransform>
        <Interactivity:Interaction.Behaviors>
            <Core:EventTriggerBehavior EventName="Click">
                <Behaviors:IsEnabledCondition 
                    IsEnabled="{Binding IsOn, ElementName=toggleSwitchAnimate}">
                    <Media:ControlStoryboardAction 
                        Storyboard="{StaticResource Storyboard1}" />
                </Behaviors:IsEnabledCondition>
            </Core:EventTriggerBehavior>
        </Interactivity:Interaction.Behaviors>
    </Button>
    <ToggleSwitch x:Name="toggleSwitchAnimate"
                    Header="Animate"
                    HorizontalAlignment="Left"
                    Margin="87,220,0,0"
                    VerticalAlignment="Top"
                    IsOn="True" />

</Grid>

Closure and download

I hope you like my solution. Maybe you can use it in your apps too. I plan to write many more conditional actions so check out my blogs for more posts. You can download my code below.

Cheers,

Fons

Download

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.

Leave a comment

Blog comments

Jerry Nixon

31-Oct-2013 6:21
Brilliant. This should be built-in. It isn't. So your code should be standard in every developer's default project template. Excellent work.

Alexandre

05-Feb-2014 5:57
Hello, Your solution don't works with a binding in a viewmodel !? why ?