Reputation: 2363
I have a style with the following triggers defined:
<Style TargetType="{x:Type graphicElements:MyTabItem}" x:Key="StMyTabItemBase">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="SelectedColor" Value="{Binding ApplicationColor, RelativeSource={RelativeSource AncestorType=graphicElements:MyTabControl}}" />
<Setter Property="Expanded" Value="False" />
<Setter Property="BorderBrush" Value="#FFACACAC"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="SnapsToDevicePixels" Value="False" />
<Setter Property="Template" Value="{StaticResource CtTabCollapsed}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSideBarExpanded, RelativeSource={RelativeSource AncestorType=graphicElements:MyTabControl}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="Expanded" BeginTime="0" Duration="0">
<DiscreteBooleanKeyFrame Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="Expanded" BeginTime="0:0:0.25" Duration="0">
<DiscreteBooleanKeyFrame Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
<Trigger Property="Expanded" Value="True">
<Setter Property="Template" Value="{StaticResource CtTabExpanded}" />
</Trigger>
</Style.Triggers>
</Style>
This works perfectly when I apply the direct style. However, I want to be able to create styles based on this style to override specific properties like margins and colors. I have tried to do so as follows (this creates a default based on this style):
<Style TargetType="{x:Type graphicElements:MyTabItem}" BasedOn="{StaticResource StMyTabItemBase}" />
However, as soon as I do that it no longer triggers or switches the template properly. If I copy just the triggers into the new style it works again, but I don't want to have to put the triggers into each style individually... Why aren't these inheriting like they are supposed to? Or do I misunderstand something about BasedOn and Triggers?
EDIT
Here is the 'BasedOn' style that works:
<Style TargetType="{x:Type graphicElements:AutodeskTabItem}" BasedOn="{StaticResource StAutodeskTabItemBase}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSideBarExpanded, RelativeSource={RelativeSource AncestorType=graphicElements:AutodeskTabControl}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="Expanded" BeginTime="0" Duration="0">
<DiscreteBooleanKeyFrame Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="Expanded" BeginTime="0:0:0.25" Duration="0">
<DiscreteBooleanKeyFrame Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
<Trigger Property="Expanded" Value="True">
<Setter Property="Template" Value="{StaticResource CtTabExpanded}" />
</Trigger>
</Style.Triggers>
</Style>
Basically I just copied out the triggers portion of the base style. However I don't understand why I have to do that...
Upvotes: 0
Views: 443
Reputation: 12276
I'm not sure about "supposed to" but your exit storyboard definitely won't find the first.
I recently came across this behaviour. It's an oddity to do with namescope. That won't work.
You could try starting another storyboard targeting the same property with 0 duration and hope that stops it. This did not work in my case.
The way I work round this in my app is to use a multiconverter to start and stop the storyboard.
My converter:
public class MultiAnimatorConverter : MarkupExtension, IMultiValueConverter
{
public Storyboard sb { get; set; }
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
// 0 = Shape
// 1 = Tag
Shape shape = values[0] as Shape;
if(shape.Tag.ToString() == "False")
{
sb.Stop(shape);
sb.Remove(shape);
}
else
{
sb.Begin(shape, true);
}
return true; // Abusing isenabled so I don't need another attached dependency property
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
You may prefer an attached property to enabled. Useage:
<Setter Property="IsEnabled">
<Setter.Value>
<MultiBinding Converter="{ui:MultiAnimatorConverter sb={StaticResource MarchinAntsAnimation}}">
<Binding RelativeSource="{RelativeSource Self}"/>
<Binding Path="Tag" RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</Setter.Value>
</Setter>
My storyboard is a separate resource.
Storyboard.TargetProperty="(Shape.StrokeDashOffset)" RepeatBehavior="Forever" From="0" To="8" Duration="00:00:.8" Timeline.DesiredFrameRate="10" />
This is used in my Map Editor ( for our game ). The user is drawing the map for a scenario. They draw terrain. Woods, rivers, contours etc. All are polygons with different templates and I use basedon to inherit so all would get the same "marching ants" animation with dotted lines animated round them when the terrain is selected for editing.
Upvotes: 1