I've found a solution that I am quite happy with.
First I defined two VSM states on my LayoutRoot Grid 'SearchInProgress' and 'Normal'.
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Standard">
<VisualState x:Name="SearchInProgress">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SearchButton" Storyboard.TargetProperty="(Control.IsEnabled)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<system:Boolean>False</system:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SearchCancelButton" Storyboard.TargetProperty="(Control.IsEnabled)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<system:Boolean>True</system:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Pretty simplistic and I might adapt them but it works.
To switch between the states I use the DataStateBehavior from here which lets me bind to a Property on the datacontext (viewmodel) and switch between two states accordingly:
<interactivity:Interaction.Behaviors>
<exprsamples:DataStateBehavior Binding="{Binding Path=SearchIsInProgress, Mode=TwoWay}"
Value="True"
TrueState="SearchInProgress"
FalseState="Normal">
</exprsamples:DataStateBehavior>
</interactivity:Interaction.Behaviors>
I think I'm now able to use the power of the VSM, designability in Blend and the flexibility of the 'DataTrigger' mechanism to full effect.