adamjcooper.com/blog

Enterprise Software Development in C#


Silverlight ListBox SelectedItem/SelectedIndex Visual State Bug Workaround

There is a UI bug in Silverlight 2 Beta 2's ListBox that has become a problem for me recently: When you set the SelectedItem or SelectedIndex property to programatically alter the current selection, the internal state of the ListBox is correctly updated, but the visual representation is not. From the user's perspective, it appears that nothing has been selected. You can read more about this bug at Delay's Blog (make sure you scroll down to the section titled "ListBox Bugs").

Delay offers a workaround, but it suffers from a flaw that you don't want to use in production code: each time his workaround is executed, a new but identical event handler is assigned to the LayoutUpdated event so that the more the workaround is used the larger the event handler list grows and the more redundant code is executed each time. It's both a memory leak and a potential performance bottleneck. Delay himself acknowledges the problem in the comments of his blog. But his basic idea, which is all he was trying to share, is sound.

So here is an updated version of Delay's workaround which you should be able to use in production code. Rather than using extension methods which you must explicitly call each time you set SelectedItem or SelectedIndex, this version extends the ListBox class. You can use this class as a replacement for the Silverlight 2 Beta 2 ListBox and the UI will correctly update when you change SelectedItem or SelectedIndex.

using System;

namespace Cooper.Silverlight.Controls
{
    public class ListBox : System.Windows.Controls.ListBox
    {
        private bool _visualSelectionNeedsUpdating;
        private int _selectedIndex;

        public ListBox()
            : base()
        {
            LayoutUpdated += new EventHandler(ListBox_LayoutUpdated);
        }

        private void ListBox_LayoutUpdated(object sender, EventArgs e)
        {
            if (_visualSelectionNeedsUpdating)
            {
                //Toggle value to force change
                base.SelectedIndex = -1;
                base.SelectedIndex = _selectedIndex;
                
                VisualSelectionNeedsUpdating = false;
            }
        }

        private bool VisualSelectionNeedsUpdating
        {
            get
            {
                return _visualSelectionNeedsUpdating;
            }
            set
            {
                _visualSelectionNeedsUpdating = value;

                if (_visualSelectionNeedsUpdating)
                    _selectedIndex = SelectedIndex;
            }
        }
        
        public new int SelectedIndex
        {
            get
            {
                return base.SelectedIndex;
            }
            set
            {
                base.SelectedIndex = value;

                VisualSelectionNeedsUpdating = true;
            }
        }

        public new object SelectedItem
        {
            get
            {
                return base.SelectedItem;
            }
            set
            {
                base.SelectedItem = value;

                VisualSelectionNeedsUpdating = true;
            }
        }
    }
}

This solution does not address the ListBoxItem class's IsSelected property, but for my needs it is acceptable until RTM.

Thanks for showing us the way, Delay.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

Add comment


(Will show your Gravatar icon)  

  Country flag

biuquote
  • Comment
  • Preview
Loading





 
Powered by BlogEngine.NET 1.4.5.0 | Design by adamjcooper