Aniak
Topic Author
Posts: 10
Joined: 27 Nov 2018, 14:41

Storyboards in ControlTemplate

23 Jan 2019, 12:31

Hi,
I've got a bunch of controls that I want to share the same behavior (some storyboards).
My approach was to create ControlTemplate with mentioned storyboards and bind it to controls through DynamicResource like that:
<Control x:Name="CTRL" VerticalAlignment="Top" Width="80" Template="{DynamicResource behavior}" Margin="193.662,16,0,0" HorizontalAlignment="Left" >

<ControlTemplate x:Key="some behavior" TargetType="{x:Type Control}">
	<ControlTemplate.Resources>
		<Storyboard x:Key="Action1">
		</Storyboard>
		<Storyboard x:Key="Action2">
		</Storyboard>
		<Storyboard x:Key="Action3">
		</Storyboard>
	</ControlTemplate.Resources>
</ControlTemplate>
but Begin() on storyboards doesn't work or I'm doing it the wrong way:
ControlTemplate *pTemplate = control->GetTemplate();
if (pTemplate)
{
	Storyboard *storyboard = NsStaticCast<Storyboard*>(pTemplate->GetResources()->FindName("Action1"));
	if (storyboard)
	{
		storyboard->Begin(control);
	}
}
What am I doing wrong? Or there is a better way to gave a controls common behavior.
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: Storyboards in ControlTemplate

23 Jan 2019, 18:40

Hi and welcome to NoesisGUI forums,

Just to make sure I understand the scenario you want to solve, do you want to share the same behavior (animations) between different control types (Button, Label, TextBox, ListBox)? Or between different instances of the same control type?
 
Aniak
Topic Author
Posts: 10
Joined: 27 Nov 2018, 14:41

Re: Storyboards in ControlTemplate

24 Jan 2019, 08:03

Hi,
these are accualy different instances of the same control type (custom control for a game hud graphically showing states of some item). I'm new in Noesis, so maybe I should choose another approach to this problem.

Thank you for roseponding.
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: Storyboards in ControlTemplate

24 Jan 2019, 10:58

In case you are talking about a particular type of control then the best way to implement this is by triggering your behavior animations with data properties.
A ControlTemplate is made of a VisualTree that defines the appearance of the control using other UI elements, and Triggers that define how these UI elements change depending on the state of the control given the values of its properties.
For example, a Button control template can look like this:
<ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
    <Border x:Name="Bg"
        Background="{TemplateBinding Background}"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="{TemplateBinding BorderThickness}"
        Padding="{TemplateBinding Padding}"
        CornerRadius="1">
        <ContentPresenter
            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="BorderBrush" Value="{StaticResource OverBdBrush}"/>
            <Setter Property="Background" Value="{StaticResource OverBgBrush}"/>
            <Setter Property="Foreground" Value="{StaticResource OverFgBrush}"/>
        </Trigger>
        <Trigger Property="IsPressed" Value="True">
            <Setter Property="BorderBrush" Value="{StaticResource PressBdBrush}"/>
            <Setter Property="Background" Value="{StaticResource PressBgBrush}"/>
            <Setter Property="Foreground" Value="{StaticResource OverFgBrush}"/>
        </Trigger>
        <Trigger Property="IsKeyboardFocused" Value="True">
            <Setter Property="BorderBrush" Value="{StaticResource FocusBdBrush}"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="BorderBrush" Value="{StaticResource DisabledBdBrush}"/>
            <Setter Property="Background" Value="{StaticResource DisabledBgBrush}"/>
            <Setter Property="Foreground" Value="{StaticResource DisabledFgBrush}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
With the previous triggers and setters the Button will change the value of some properties for named elements inside the VisualTree to reflect the appearance of the new visual state.
You can do the same with your control and any dependency properties you want to expose.

There is also another option to define how a control should look depending on different states of the control, by using a VisualStateManager inside its ControlTemplate. You can read more about this topic here:
http://miteshsureja.blogspot.com/2011/0 ... re-in.html
http://miteshsureja.blogspot.com/2011/0 ... n-wpf.html

Default controls in Noesis define its own default states like MouseOver, Pressed, Disabled, Selected, Unselected, Focused, Unfocused, ...
With this approach you will be able to define custom VisualStates for your control that you can trigger from code:
void MyControl::ChangeState(State state)
{
  if (state == State::Alive)
    GoToState(NsSymbol("Alive"));
  else
    GoToState(NsSymbol("Dead"));
}
<VisualStateGroup x:Name="PlayerStates">
    <VisualStateGroup.Transitions>
        <VisualTransition GeneratedDuration="0:0:0.5"/>
    </VisualStateGroup.Transitions>
    <VisualState x:Name="Alive"/>
    <VisualState x:Name="Dead">
        <Storyboard>
            <ColorAnimationUsingKeyFrames
                    Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                    Storyboard.TargetName="ellipse">
                <EasingColorKeyFrame KeyTime="0" Value="#FF80050E"/>
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
</VisualStateGroup>
NOTE: Whenever is possible use StaticResource to refer to previously defined resources, that way you avoid creating an expression that is listening for resource changes in the UI tree.
 
Aniak
Topic Author
Posts: 10
Joined: 27 Nov 2018, 14:41

Re: Storyboards in ControlTemplate

24 Jan 2019, 14:33

Thank you, the approach with VisualStateManager worked great.

Who is online

Users browsing this forum: vinick and 23 guests