Add ability to disable availibility effects on an action message?

Jan 19, 2011 at 3:24 AM

Scenario: A ListBox and button both tied to to two to the same method (Edit) on the viewmodel via two different XAML ActionMessage objects to edit the selected item of a ListBox.

The first control, a button, is tied to the Edit method via an xaml declared ActionMessage,  the ViewModel has a CanEdit property that returns false if the SelectedItem is null which also disables the button, this is the desired effect, and forced the user to select an item in the ListBox to enable the Edit button.

I have another action message tied to the same method, but triggered by the double click of a ListBox item. For Example:

 

 
<ListBox SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}" x:Name="MyItems">
    <i:Interaction.Triggers>
        <BlendTriggers:UXListBoxItemMouseDoubleClickTrigger>
            <cal:ActionMessage MethodName="EditRequest" >
                <cal:Parameter Value="{Binding Path=SelectedItem}"/>
            </cal:ActionMessage>
        </BlendTriggers:UXListBoxItemMouseDoubleClickTrigger>
    </i:Interaction.Triggers>
</ListBox>

 

The problem is that this makes the listbox disabled and i can't enable it because now i can't click on a listbox item to set the selected item from not null. It would be nice to have a property on ActionMessage akin to (bool DisableAvailibilityEffects). I know this a minor thing and there's a dozen or so ways to work around this, just thought I throw it out there to see if this is desirable by anyone else.

Coordinator
Jan 19, 2011 at 2:03 PM

I'm not going to add this. But, you can add it quite easily yourself. First, create a new type of message that inherits from ActionMessage and add your custom property DisableAvailabilityEffects to that. Next, replace the ActionMessage.ApplyAvailabilityEffect func with your own which grabs the message from the context, checks to see if it is your custom message type and checks the custom property. If true, return. If false, call the original implementation.

Jan 19, 2011 at 9:40 PM
Edited Jan 20, 2011 at 12:38 AM

Thanks Rob, I agree, I was pretty much thinking on the same lines, thanks for the quick response.

For the curious, here's my implementation:

    public class ActionMessageEx : ActionMessage
    {
        private static readonly Type ThisType = typeof(ActionMessageEx);
        
        #region DisableAvailabilityEffects Dependency Property
        public static readonly DependencyProperty DisableAvailabilityEffectsProperty =
            DependencyProperty.Register(
                "DisableAvailabilityEffects",
                typeof(bool),
                ThisType,
                new PropertyMetadata(false));
        
        public bool DisableAvailabilityEffects
        {
            get { return (bool)GetValue(DisableAvailabilityEffectsProperty); }
            set { SetValue(DisableAvailabilityEffectsProperty, value); }
        }
        #endregion DisableAvailabilityEffects Dependency Property
    }

And in the bootstrapper's Configure override I call:

        
private static readonly Func<ActionExecutionContext, bool> OriginalApplyAvailabilityEffectFunc 
            = ActionMessage.ApplyAvailabilityEffect;

        private static void SetCustomActionMessageApplyAvailabilityEffectFunc()
        {            
            ActionMessage.ApplyAvailabilityEffect = context =>
                {
                    var actionMessageEx = context.Message as ActionMessageEx;

                    if (actionMessageEx != null && actionMessageEx.DisableAvailabilityEffects)
                    {
                        return false;
                    }

                    return OriginalApplyAvailabilityEffectFunc(context);
                };
        }