7

I'm moving a object over a bunch of Buttons, and when this object is over a button I change the color of the border. This is no problem, I can do this through bindings, storyboards or style setters/Visual state. When I run this on my emulator it works nice and smooth, but when I run it on my windows phone, there is a small lag when the Border of the country changes. Is there a way to avoid this?

1. CODE Example

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

and activation

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;
    }
}

Extra

One difference which comes to mind between emulator and an actual device is the accuracy of the touch point. In the emulator you use a mouse which has much higher resolution. On a device where you're using your finger the accuracy is much lower, i.e. millimeters vs pixels.

I just tested this with a simple counter and a break point in the manipulation_completed_event. But the count is the same in both cases. And it only tried to run the storyboard once.

Extra2

To clarify the lag I see:

I am dragging an element that follows the finger smoothly, when I cross into a new buttton, the element I am dragging stops a short while. The color of the button is changed and the element moves again.

When I move back after the button has changed the color. The element moves smoothly with my finger when I move between the buttons.

Therefore there is a lag when the storyboard is activated and it is seen in that the element I drag cannot follow the finger.

I am therefore trying to find alternativ ways to change the color that might have better performance, on the Phone. Beacuse it works fine on the emulator.

I have tested on two different lumia 920s and one lumia 520

2. Code Example

Using Visual State Manager with help from Shawn Kendrot, from another question: Using Dependency object for color animation WP8 replicated below:

<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);
}

Still with lag, Anyone else have a solution that could be tested?

Extra

Since the issue might be low fps, i.e. a render problem when I want to change the color, could the dispatcher be used ?

So in the first code example where I start a storyboard, I could instead call a function in the view to utilize the dispatcher? Anyone has an idea for doing this and or if it is a good idea?

appreciating all the help, since I cannot understand why I can move objects smooth around on the screen but when I want to change the color of the border I can see it lagging :/

Community
  • 1
  • 1
JTIM
  • 2,774
  • 1
  • 34
  • 74
  • As stated in the question i have tried many solutions with no success and sharing code of a button did not seem fitting. @AMR my question is directed at what method could be used to remove lagging. I have looked at memory usage for all the different solutions with no real impact. But on the emulator everything works fine. – JTIM Apr 11 '14 at 16:00
  • 1
    if you cannot provide code then this question is off topic for Stack Overflow. The code is relevant on this site. – DotNetRussell Apr 11 '14 at 16:09
  • Do you have events fired when you start the storyboard or something like that? – csharpwinphonexaml Apr 11 '14 at 16:14
  • @AMR it is not a problem of adding code it is if its relevant. Here I added one example. My problem is not that they are not working more that they are lagging. So I wanted to know of a way people might have used without forcing my ideas upon them. – JTIM Apr 11 '14 at 16:15
  • @JTIM this isn't your personal Q and A blog. When you post here you are creating a historical document that others can reference when they have similar issues. The reason your exact code is needed is so your exact problem can be identified and fixed. Two people can have the same issue but one person it is because they set the wrong property and another person is using a deprecated DLL. Without having your exact code this distinction cant be made and is not only impossible to fix but also useless to future readers – DotNetRussell Apr 11 '14 at 16:18
  • How many Path are involved in this? I Would suggest one Storyboard with multiple Animations rather then one storyboard per path since each storyboard has it's own thread – csharpwinphonexaml Apr 11 '14 at 16:18
  • @verdesrobert there is many buttons and it should only some of the buttons should be activated. Therefore it is nested under each button. such that I can run the storyboard for the respective UI element. So creating one big animation is not a solution. And I could not see that removing the lag, but rather introducing more? – JTIM Apr 11 '14 at 16:20
  • @JTIM Also I have removed my down vote and retracted my close vote. Thank you for providing your code – DotNetRussell Apr 11 '14 at 16:20
  • So you say that there are not concurrent storyboards started? – csharpwinphonexaml Apr 11 '14 at 16:21
  • @JTIM what device are you using? I have noticed performance differences in the HTC devices compared to Lumias – DotNetRussell Apr 11 '14 at 16:21
  • @AMR It was 2 lumia 920s and one lumia 520. Do not have access to the HTC. It is perfectly fine and thank you. – JTIM Apr 11 '14 at 16:23
  • @verdesrobert No does not seem to be the issue when I tested with slow movement or fast. The lag occurs when crossing the buttons border and changing the color of the new element. – JTIM Apr 11 '14 at 16:25
  • is your event firing only once after object moves over the button or is firing again and again as the object moves? As that could be a reason for the lag – Rishabh876 Apr 17 '14 at 14:02
  • you can also try without the debugger attached as that also affects the performance. – Rishabh876 Apr 17 '14 at 14:05
  • @Rishabh876 I had in the start that I could have it firing 70 times. I.e. allways when moving. This was not a problem on the emulator. But I removed it for the phone, so it only fires once. And when it is fired in lags on the Phone, but not on the emulator. No difference when using release. Any ideas of how to improve performance? Maybe another way or better way :)? – JTIM Apr 17 '14 at 19:39
  • This question looks identical to http://stackoverflow.com/questions/22536998/using-dependency-object-for-color-animation-wp8/22647026#22647026 – Shawn Kendrot Apr 22 '14 at 20:04
  • @ShawnKendrot yeah I can see it is nearly the same, at least the code. The other had no working solution, this was to try another question around the topic. – JTIM Apr 23 '14 at 06:11
  • Have you tried looking at drop/drop functionality. This is essentially what you're trying to do, even if no plans to drop. DragDrop allows you to listen to a DragOVer which would be helpful. – Shawn Kendrot Apr 23 '14 at 17:22
  • I have drag. I use that in the manipulationDeltaEvent. And cannot see another event would be any difference? The problem is my animation, fired once, it makes the app lag. i.e. the element I am dragging stops for short while before it moves. This only occurs when the color changes, else the drag is smooth. Therefore I was looking for another way to change the color. I tried from the question visualstate still the same lag. Any other way to change the border? – JTIM Apr 23 '14 at 18:43
  • Have you tried, instead of changing the visual state, to set the button border color using "((Control)sender).BorderBrush = new SolidColorBrush(Colors.Red);" ? – Miiite May 07 '14 at 15:02
  • @JTIM i think (pure guess) this is a rendering problem, can you try to change the opacity to .99 – Swift Sharp May 08 '14 at 10:16
  • @Miiite That was the first try, did not work. Should be noted it is not done in an event so therefore I do not have sender. But still lagging. And also if I use binding and change it using that. – JTIM May 08 '14 at 11:22
  • @SeeSharp I tried setting opacity on the whole button, did not solve the issue. – JTIM May 08 '14 at 11:29
  • @SeeSharp I have also tried only the border also with no success. – JTIM May 09 '14 at 12:04
  • @JTIM do you have appbar in your page – Swift Sharp May 09 '14 at 13:25
  • No everything on the page is running with usercontrols. They are created from Paths created in blend. – JTIM May 09 '14 at 15:20
  • I added in my answer the idea of using the dispatcher, could that Be a solution? – JTIM May 09 '14 at 15:21
  • Have you looked at specifying a 0 duration on an added [VisualTransition](http://msdn.microsoft.com/en-us/library/system.windows.visualtransition(v=vs.110).aspx)? – Chris W. May 12 '14 at 16:18
  • @ChrisW. No I have not, the reason was that as far as I know it is only possible to then specify one colour? I wanted to be able to decide if it should be green or red, as an example. Is this possible, from the link and what I know it does not seem like it? – JTIM May 12 '14 at 17:11
  • I mean specifying the transitions for the `From` and `To` between the `VisualStates` directly. I may have to read the whole question again with more attention, I do sometimes tend to hastily speed-read through SO posts without proper consideration. – Chris W. May 12 '14 at 17:55
  • @ChrisW. No I think I have not specified this issue, that I want to be able to specify different colors. Yes the to and from, might be possible. But I want to be able to have different colors for different times. That was why i used the events and could there specify which visualstate I wanted to use. But the visualtransition, seems to be you only use the visualstates, and therefore I cannot make logic for which color to use, as I could with the events and visualstates. Is this possible? Else it is a bit the same as using visualstates but that still lagged. – JTIM May 12 '14 at 18:38

2 Answers2

3

I've had performance issues on animations in my apps, and often solved them by setting the CacheMode property to BitmapCache on elements that move.

The idea is that it indicates the framework take a screenshot of the control and store the resulting bitmap in the GPU's memory, so that the control doesn't have to be redrawn on every frame.

You can look at this article: CacheMode and why it matters for more insight.

Olivier Payen
  • 15,198
  • 7
  • 41
  • 70
  • Yes that is true, we have used that for other animations. And also tried it here, but with this issue no success. – JTIM May 12 '14 at 13:47
1

What are the debug/performance info you get when running attached to debugger?

Enable them adding the following at the end of App constructor:

        // Show graphics profiling information while debugging.
        if (Debugger.IsAttached)
        {
            // Display the current frame rate counters.
            Application.Current.Host.Settings.EnableFrameRateCounter = true;

            // Show the areas of the app that are being redrawn in each frame.
            //Application.Current.Host.Settings.EnableRedrawRegions = true;

            // Enable non-production analysis visualization mode,
            // which shows areas of a page that are handed off to GPU with a colored overlay.
            //Application.Current.Host.Settings.EnableCacheVisualization = true;

            // Prevent the screen from turning off while under the debugger by disabling
            // the application's idle detection.
            // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
            // and consume battery power when the user is not using the phone.
            PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
        }
roalz
  • 2,699
  • 3
  • 25
  • 42
  • It is enabled, I am a bit unsure what numbers you want of them. But when the lagging occurs I have the following: 030 030. Which I think is the framerate. I have the same when just moving the item, and therefore does not seem to be the problem. The last number is 01.4333 and falls to 01.4000 when the lag occurs. The numbers in order is 030 030 022974 008 000 01.4333 – JTIM May 08 '14 at 11:28
  • There's a nice post about WP frame rate counters here: http://www.jeff.wilcox.name/2010/07/counters/ There should also be an official one on Microsoft websites, but I can't find it now. On my Nokia 925 I have around 060 for both the first two numbers (which means 60 fps on render and UI threads. If those numbers drop (and turn red), it may be a rendering issue. Your numbers are probably low because of the lower-end hardware (?) What about other performance metrics (i.e. from Visual Studio, Debug menu, "Start Windows Phone Application Analysis")? – roalz May 09 '14 at 11:03
  • I have low memory usage around 50 mb. My device that I Tested the above was a 920, which should be capable of doing the 60 fps. Want issue can be the fault of the rendering issue, what it only occurs during the border color change. – JTIM May 09 '14 at 12:05
  • I added in my question am Idea of using the Dispatcher because of what you said I found this link, regarding performance [http://blogs.windows.com/windows_phone/b/wpdev/archive/2013/01/25/building-high-performance-windows-phone-apps.aspx] and it seems like it could be a possibility? – JTIM May 09 '14 at 12:14