WPF Scrolling Performance Tip: Avoid using ScrollBarVisibility=Auto
14 August 06 09:19 AM | henryh | 7 Comments   

When you can, avoid using the ScrollBarVisibility value "Auto" for HorizontalScrollBarVisibility and/or VerticalScrollBarVisibility.  These properties show up on ScrollViewer, TextBox , RichTextBox and ListBox (although, as an attached property on the last.)  Instead, use "Visible", "Disabled" or "Hidden."

The "Auto" value is intended for cases when space is limited and ScrollBars should only be displayed when necessary.  For example, it may be useful with a ListBox of 30 items as opposed to a TextBox with hundreds of lines or more of text.

WPF Performance: TextBoxes Galore!
11 August 06 06:17 PM | henryh | 5 Comments   

I see a lot of WPF demos, repros, apps and so forth on a regular basis.  Sometimes these apps will contain, for whatever reason, a large number of TextBoxes.  Now, I have my opinions about whether or not UI looks good with that many TextBoxes but I have a stronger opinion on what should be done to make sure performance isn't significantly impacted.

 

(I suggest you read the "Background" below but if you just want the code, you can skip it.)

Background

A post or two ago I mentioned that keeping track of your application's element count was important for performance (specifically, keeping the number as low as possible.)  Frequently, this includes knowing how many elements you're introducing.  Lets do some numbers.

 

The Numbers

A fully "template expanded" TextBox contains 30 elements (including ScrollBars.)  A minimally expanded TextBox has 10 elements.  Now, imagine you have 100 minimally expanded TextBoxes - that's 1000 elements!  Even if you haven't explicitly added TextBox elements yourself, you may have one in an ItemTemplate of an ItemsControl; this can easily increase the number of instances.

 

Step # 1

So, now I’ve told you what the potential problem is; only fair I should give a solution.

Well, the first question I ask is "Are the TextBoxes necessary?"  In some cases, using a TextBox is overkill and you can get away with using a TextBlock or a Label control.  Here are some simple guidelines:

 

  • Use TextBox if you need:
    • Text selection
    • The ability to edit the text
  • Use TextBlock or Label if you only need:
    • To display text
    • To show text of a changing value.

Step # 2

At this point, let’s say that you do need a TextBox (or many.)  Now what?  By simply dynamically changing the Template of a TextBox from 10 elements to just two – per instance!  So, with 100 minimally expanded TextBoxes we go from 1000 elements to 208!  So how do you do it!?  With some Xaml & some C#.

 

Xaml

Below, you’ll find the Xaml necessary for this demonstration (code‑behind is required; shown below the Xaml.)

 

Notice that there are four TextBoxes (with varying text formatting) and a couple of Styles named TextBoxBaseStyle and BasicTextBox.  TextBoxBaseStyle is just a set of common properties I used across the TextBoxes.  BasicTextBox is the simplied, or lighter weight, version of TextBox that can be used when selection or text editing aren’t needed.  The idea is to swap the templates at the right time (notice the MouseLeftButtonDown handler on the parent StackPanel.)

 

It’s basically that easy along with the code below (modify the code to the behavior you want.)

 

<Window x:Class="TextBoxPerformance.Window1"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:sys="clr-namespace:System;assembly=mscorlib"

    Title="TextBoxPerformance" Height="300" Width="300"

    >

 

 

 

  <StackPanel MouseLeftButtonDown="HandleMouseInput" Margin="5">

   

    <StackPanel.Resources>

 

 

      <!--

            Base TextBox Style

-->

 

      <Style x:Key="TextBoxBaseStyle" TargetType="{x:Type TextBox}">

        <Setter Property="FontSize" Value="20"/>

        <Setter Property="Margin" Value="5"/>

      </Style>

 

 

<!--

            Simplified TextBox Style with template & necessary

            bindings.

-->

     

      <Style

        x:Key="BasicTextBox"

        TargetType="{x:Type TextBox}"

        BasedOn="{StaticResource TextBoxBaseStyle}">

 

        <Setter Property="Template">

          <Setter.Value>

            <ControlTemplate TargetType="{x:Type TextBox}">

              <Border

                BorderBrush="{TemplateBinding BorderBrush}"

                BorderThickness="{TemplateBinding BorderThickness}"

                Background="{TemplateBinding Background}"

                >

                <TextBlock

                  Margin="3.85,2,3.85,2"

                  Text="{TemplateBinding Text}"

                  TextDecorations="{TemplateBinding TextDecorations}"/>

              </Border>

            </ControlTemplate>

          </Setter.Value>

        </Setter>

 

        <Setter Property="Focusable" Value="false"/>

      </Style>

    </StackPanel.Resources>

 

 

<!--

            A sample of TextBoxes with various formatting properties.

-->

 

    <TextBox

Style="{StaticResource BasicTextBox}"

FontFamily="Georgia"

Foreground="green"

FontWeight="Heavy">Athens</TextBox>

 

    <TextBox

Style="{StaticResource BasicTextBox}"

FontFamily="Garamond">Chicago</TextBox>

 

    <TextBox

Style="{StaticResource BasicTextBox}"

FontFamily="Comic Sans MS"

FontStyle="Italic">Springfield</TextBox>

 

    <TextBox

Style="{StaticResource BasicTextBox}"

FontFamily="Arial" Foreground="red"

TextDecorations="underline">Urbana-Champaign</TextBox>

  

 

  </StackPanel>

</Window>

 

 

 

using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Input;

 

 

 

namespace TextBoxPerformance

{

 

      //Generated code from WPF Project in VS

 

    public partial class Window1 : System.Windows.Window

    {

        public Window1()

        {

            InitializeComponent();

        }

 

 

      //Used to track whether or not another TextBox

      //is active.

 

        private TextBox ActiveTextBox;

 

 

      //Actives the hit TextBox if one isn’t active.

      //Deactivates the active TextBox if something

      //else was hit.

 

        void HandleMouseInput(object sender, MouseEventArgs args)

        {

            TextBox tb = args.Source as TextBox;

 

            if (tb == null)

                return;

 

            if(ActiveTextBox==null)

                Activate(tb);

            else

                Deactivate(ActiveTextBox);

 

        }

 

 

      //Deactivates the active TextBox if the Enter

      // or ESC key is pressed.

 

        void HandleKeyInput(object sender, KeyEventArgs args)

        {

 

            TextBox tb = args.Source as TextBox;

 

            if (tb!=null &&

                  (args.Key == Key.Return || args.Key== Key.Escape))

 

                Deactivate(tb);

        }

 

 

      //Deactivate the Textbox the active TextBox.

 

        void HandleLostFocus(object sender, EventArgs args)

        {

            TextBox tb = sender as TextBox;

            if (tb != null)

                Deactivate(tb);

        }

 

 

      //Activate the TextBox by applying the base style

      //(thereby removing the basic style.)  Set focus, select

      //all the content & invalidate the visual.

      //Also, dynamically add handlers for losing focus and

      //handling key input.

 

        void Activate(TextBox tb)

        {

            tb.Style = (Style)tb.FindResource("TextBoxBaseStyle");

            tb.Focus();

            tb.SelectAll();

            tb.InvalidateVisual();

           

            tb.LostFocus += new RoutedEventHandler(HandleLostFocus);

            tb.KeyDown+=new KeyEventHandler(HandleKeyInput);

 

            ActiveTextBox = tb;

 

 

        }

 

      //Deactivate the TextBox by applying the Basic style.

      //Remove the event handlers.

 

        void Deactivate(TextBox tb)

        {

            tb.Style = (Style)tb.FindResource("BasicTextBox");

            tb.LostFocus -= new RoutedEventHandler(HandleLostFocus);

            tb.KeyDown -= new KeyEventHandler(HandleKeyInput);

 

            ActiveTextBox = null;

           

        }

 

 

    }

}

 

Now, when a TextBox is clicked, it becomes editable.  When RETURN or ESC is pressed, the value is committed.

 

 

WinFX B2 Ships! Got Perf?
25 May 06 03:48 PM | henryh | 1 Comments   

I am very excited that we shipped B2!!  Wahoo!  Not only am I excited because I've been working on the product a long time but also because we made so much great performance improvements in WPF in B2 that everyone gets to see!

Yes, there are still areas that we need to work on and we are but the perf work that made it into B2 should be visible across the platform.  I'm not going to be able to list everything here but we made a lot of headway on both working set and cpu utilization.

I wanted to highlight one new API that we added to help in throttling frame rate when you don't need 60 fps.  You can set the StoryBoard.DesiredFrameRate now to control the animation fps.  The lower the number, the less CPU utilization you should see.

As always, I love hear feedback.

-Henry

WPF Perf, Element Count, Panels and Controls
02 May 06 09:35 AM | henryh | 1 Comments   

I got a question about WPF performance this morning regarding how the number of elements (controls, panels, et al.) affects performance.  Before I share more broadly, I'll mention that the WPF Performance team is working on plans for more detailed & prescriptive guidance; you should stay tuned here & MSDN for more info.  In the mean time, here's the response I provided:

--------

There is a cost for additional elements that you add; to name a few: 

  1. Working set – you’ve got more elements and more state that consumes memory.
  2. Layout – you’re performing more layout work even if these are fairly simple calls.
  3. Property invalidations – when a property changes there’s more work to update affected values.
  4. Hit testing – more elements to check when input is received.

One of the key ways to improve performance of your app is to reduce the number of elements.  You can do this in a variety of ways: 

  • Use virtualization when you can in ItemsControls using the VirtualizingStackPanel.
  • Use the Grid element as a top‑most layout when you have a fairly complex & nested layout instead of several panels.
  • Reduce the number of elements in and depth of templates when you can.
Where have I been? WPF Performance!
01 May 06 10:29 AM | henryh | 0 Comments   

It's been a long while since I've posted to my blog.  What have I been up to?  Basically, since the PDC I've been working on WPF performance.  We've been working on reducing CPU consumption, memory consumption and, in some case, GPU consumption.

One of the things that I'd like to start doing is posting some snippets on some of the stuff we (the WPF Perf Team) learned as we've working on the performance of the platform.  For example, if you take a look at a profile of your WPF application, how do you know what to look for?

I'll start with small tidbits, though:)

Perf Tip: Use BitmapEffects sparingly.  BitmapEffects run entirely in software and cuase scenes which frequently invalidate to be very expensive to update (for example, from animations.)  BitmapEffects are best used on small static UI.

Custom Scrolling with IScrollInfo
06 January 06 09:12 AM | henryh | 0 Comments   

In one of my first posts ever I talked about doing custom scrolling using the IScrollInfo interface.  Well, Ben Constable, another Microsoftie, beat me to it:)  Check it out here.

Optimizing WPF ("Avalon") Application Performance
06 October 05 10:50 AM | henryh | 1 Comments   

While we're still tuning the platform, there are tips & tricks that you can use to optimize your WPF application's performance.  Where can you find these?  Check out the performance whitepaper that Kiran has put together.  As we go, we'll update and eventually get posted on MSDN.

Windows Vista UX Guidlines
28 September 05 01:11 PM | henryh | 0 Comments   
I got a question about this while I was at the PDC.  I see they're now posted on MSDN.
Back from L.A.
18 September 05 11:27 PM | henryh | 0 Comments   
I just got back into Seattle last night.  I'll get my samples posted as soon as have some free time.
O'Reilly's Programming Windows Presentation Foundation
12 September 05 10:43 PM | henryh | 1 Comments   

I just got a look at this new book from O'Reilly written by Ian Griffiths and Chris Sells.  Good stuff.  Check it out!

In L.A.: Electricity
12 September 05 01:55 PM | henryh | 0 Comments   
Made it to L.A.!  The weather is beautiful.  Biggest event so far?  Downtown L.A. lost power for about 30 minutes (and I've been here all of about 3 hours); I was having lunch with Fil in the hotel lobby when it happened.  MSNBC already has an article.
MSN Messenger 7.5 - Free Voice Conversations!
11 September 05 09:44 PM | henryh | 0 Comments   

I just tried MSN Messenger 7.5.  What can I say?  Amazing.

The Messenger team is cookin'!  Seems like everytime I've installed a new version of MSNIM there's been some useful new feature I've found even if it seems insignificant.

MSNIM 7.5's new feature?  Free voice conversations.  A friend of mine was in Vancouver, British Columbia today when he sent me an invitation to have a voice conversation; I was in Redmond, WA.  In two minutes, I had installed MSNIM 7.5 on my Dell D600 laptop using the built-in microphone and was having a voice chat.  The quality was amazing!!  No echo, no delay, clear audio.  I don't know how they did it but I've got to get my entire contact list to install it.  Awesome.

T-Minus 3 Days
09 September 05 12:42 PM | henryh | 0 Comments   

The PDC is almost here!!!  Just imagine:  Thousands of developers descending upon L.A. to find out all about new Microsoft technologies.  But it's not just that; it's that this technology will change not only software but the world!  Even though the PDC is a lot of work and many of us here at MS could probably use a few more hours of sleep, we're all pretty fired up.  It could be the large amounts of coffee but I think it's safe to say that it's the excitement about the PDC:)

Okay, time to get back to practicing my talk.

Bill Gates' Interview on Channel 9
08 September 05 07:21 PM | henryh | 0 Comments   

Check it out! Bill does an interview on Channel 9.

PDC 2005, here I come!
26 August 05 05:10 PM | henryh | 0 Comments   

The PDC is almost here and I'm excited!

I've been working on my presentation.  I'll be giving PRS329 - Windows Presentation Foundation ("Avalon"): Building User Interface with Advanced Layout Techniques.  If there was something you wanted to know about Avalon Layout, this is a talk for you.  I'm still fine tuning the talk, so, if there are topics that you'd like to hear me discuss, drop me a line and I'll see what I can do.

See you in L.A.!

Search

This Blog

Tags

Syndication

Page view tracker