Using Dependency object for color animation WP8
Asked Answered
B

1

3

I'm using a button where I've shaped it, in its ControlTemplate. I've also added a storyboard in the controlTemplate. The storyboard changes the boarder of the element in my controlTemplate. I access this from the code behind and activate it, the problem is when I do this on the phone there is a lag. I've structured my code after the MVVM structure, my view is:

 <Button x:Name="Button1" BorderThickness="0" BorderBrush="Transparent">
        <Button.Template>
            <ControlTemplate x:Name="Control">
                <Path x:Name="Control2" Style="{StaticResource style_ColorButton}" Data="{Binding Data}" Fill="{StaticResource Background}">
                    <Path.Resources>
                        <Storyboard x:Name="StoryBoard1">
                            <ColorAnimation Storyboard.TargetName="Control2" Storyboard.TargetProperty="(Stroke).(SolidColorBrush.Color)" To="Blue" Duration="0"/>
                        </Storyboard>
                    </Path.Resources>
                </Path>
            </ControlTemplate> 
        </Button.Template>

And my the part of the ViewModel where I activate my storyboard:

   foreach (UIElement x in ElementsAtPoint)
        {
            f = x as FrameworkElement;
            if (f is Path)
            {
                try { 
                h = f as Path;
                Storyboard sb = h.Resources["StoryBoard1"] as Storyboard;
                sb.Begin();
                    }
                catch
                {

                }
                break;
            }
        }

I've read that one can use Dependency object for the animation, but I'm not sure how it works or if it will work, but any help trying to implement dependency object for the animation would be appreciated.

Bolden answered 20/3, 2014 at 15:2 Comment(6)
a very important information is: when the animation is supposed to run.Harlene
two questions, why do you have two parts named "Control" and why/when are you trying to animate this?Bonaventure
@Harlene When a user hovers above the button, I find the storyboard in the foreach loop and run the storyboard.Bolden
@ShawnKendrot That was a mistake, only suppose to be one "control", changed it now. See above comment for the rest.Bolden
@Bolden There is no "hover" in Windows Phone. What event (of which control) triggers the animation?Harlene
@Harlene didn't know you wanted the event, I'm using an manipulationDeltaEvent, but it is not for the button, but for an item which i'm moving above the buttonBolden
B
4

I would recommend using VisualStates to do what you are looking for. I modified the Style of a button to add a story to the MouseOver VisualState, then added event listeners for MouseEnter and MouseLeave to the button. These events are fired when you touch the device, and drag your finger over an element, and then drag it off again. You could modify the code below to check if something is being dragged. You could also take a look at Drag/Drop functionality.

Using the following Style

<Style x:Key="ButtonStyle" TargetType="Button">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
    <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
    <Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
    <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
    <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMedium}"/>
    <Setter Property="Padding" Value="10,5,10,6"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Background="Transparent">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Orange"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneButtonBasePressedForegroundBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneAccentBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0" Margin="{StaticResource PhoneTouchTargetOverhang}">
                        <ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Notice it has a MouseOver VisualState. Then assign the style and subscribe to the event handlers

<Button Content="Drag over me" Style="{StaticResource ButtonStyle}"  MouseEnter="OnButtonMouseEnter" MouseLeave="OnButtonMouseLeave"/>

And in the event handler change the visual state.

private void OnButtonMouseEnter(object sender, MouseEventArgs e)
{
    VisualStateManager.GoToState((Control)sender, "MouseOver", true);
}

private void OnButtonMouseLeave(object sender, MouseEventArgs e)
{
    VisualStateManager.GoToState((Control)sender, "Normal", true);
}

With this, when you tap and drag your finger over the button, it will turn orange with white text.

Bonaventure answered 25/3, 2014 at 21:48 Comment(4)
Is there a way to change the visualState from my ViewModel instead of doing it from the code behind the xaml. I tried using binding, but get an error when I assign it to the mouseEnter nad MouseLeaveBolden
There is nothing wrong with code being in your code behind. It is a UI specific thing you are trying to accomplish. You could create your own button class and in that class listen to the events. eg: `public class HoverButon : Button { public HoverButton() { /*subscribe to events*/ } /* event handlers */ }Bonaventure
I added the xam lto my buttons style and the code too, but nothing happens when I move over or leave the button. Is this because I've added the path to my control template?Bolden
I modyfied what you posted, adding the path in the <setter.value> controlTemplate and aiming the storyboards at the stroke of the path. At the moment I've got 46 of these in a map, and when I move over there's a lag. Is there a way to avoid the lag when i Change the visualState?Bolden

© 2022 - 2024 — McMap. All rights reserved.