Silverlight 4: Bug in TabControl.TabStripPlacement = Dock.Left and OnApplyTemplate

At work I ran into a bug with the Silverlight TabControl, more specifically when setting the TabStripPlacement to Dock.Left and hiding one of the TabItems in the parent’s OnApplyTemplate.

The way to get to this bug is quite specific. For example, you can’t do it when you’re using a UserControl, since in that kind of class OnApplyTemplate is never called.

You need to build a class which inherits from Control.

public class TabControlTest : Control

Then we have the style of this particular class:

<Style TargetType="TabControlTest:TabControlTest"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="TabControlTest:TabControlTest"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="38" /> </Grid.RowDefinitions> <sdk:TabControl TabStripPlacement="{TemplateBinding TabStripPlacement}" Grid.Row="0"> <sdk:TabItem Header="First"> <sdk:TabItem.Content> <TextBlock Text="A" /> </sdk:TabItem.Content> </sdk:TabItem> <sdk:TabItem Header="Second" x:Name="middleTabItem"> <sdk:TabItem.Content> <TextBlock Text="B" /> </sdk:TabItem.Content> </sdk:TabItem> <sdk:TabItem Header="Last"> <sdk:TabItem.Content> <TextBlock Text="C" /> </sdk:TabItem.Content> </sdk:TabItem> </sdk:TabControl> <Button HorizontalAlignment="Center" Grid.Row="1" Content="{TemplateBinding ShowOrHide}" Command="{TemplateBinding ShowOrHideCommand}" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>

As you can see I’ve named the middle TabItem (“middleTabItem”) so I can retrieve it in the OnApplyTemplate:

public override void OnApplyTemplate()
{
    this._middleTabItem = (TabItem) this.GetTemplateChild("middleTabItem");
    this._middleTabItem.Visibility = Visibility.Collapsed;

    base.OnApplyTemplate();
}

Now if the following 2 conditions are matched:

  1. TabStripPlacement is set to Dock.Left (it doesn’t happen on ‘Top’)
  2. We set the Visibility of the said TabItem to Collapsed in the OnApplyTemplate of the surrounding Control

Then we cannot make the TabItem Visible anymore.

To show or hide I use the following code:

this.ShowOrHideCommand = new Command(() =>
                                         {
                                            this.ShowOrHideText = string.Format(SwitchTo, this._middleTabItem.Visibility);
                                            this._middleTabItem.Visibility = this._middleTabItem.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
                                         });

The solution to this is to call the OnApplyTemplate of the TabControl itself so that it recalculates it’s children’s location (or something, I’m not sure):

Give the TabControl a name, fetch it in OnApplyTemplate of your Control:

<sdk:TabControl TabStripPlacement="{TemplateBinding TabStripPlacement}" x:Name="TabControl" Grid.Row="0">
public override void OnApplyTemplate()
{
    this._middleTabItem = (TabItem) this.GetTemplateChild("middleTabItem");
    this._middleTabItem.Visibility = Visibility.Collapsed;
    this._tabControl = (TabControl) this.GetTemplateChild("TabControl");
    base.OnApplyTemplate();
}

And call the _tabControl’s OnApplyTemplate after switching the Visibility to Visible:

this.ShowOrHideCommand = new Command(() =>
                                         {
                                            this.ShowOrHideText = string.Format(SwitchTo, this._middleTabItem.Visibility);
                                            this._middleTabItem.Visibility = this._middleTabItem.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
                                            this._tabControl.OnApplyTemplate();
                                         });

This will make the UI respond correctly. For your convenience I’ve added the SL project, and you can download it here.

Visual Studio 2010 SP1: DebuggerTypeProxy works again! *yay*

A while ago I bumped into a bug in Visual Studio 2010 + Silverlight 4.

While working with a List / Dictionary / … it didn’t show the items in the list, instead it showed the normal ‘raw view’:

No debug view

As you can see, there was no view to see the items.

What you would expect to see is this:

DebugView!

I reported the bug (many others did too!). The problem was that it was fixed in SL3, but not ported to SL4.

Now it’s fixed! This makes my work a lot easier. When we get SP1 @ work too that is!

Cheers!

Dictionary<TKey, TValue> finding key: try/catch vs TryGetValue

Today I saw some code where the developer accessed a dictionary like this:

  1. void Foo(int keyToFindInDictionary)
  2. {
  3.     Dictionary<int, string> dictionary = new Dictionary<int, string>();
  4.  
  5.     try
  6.     {
  7.         DoSomethingWithTheResult(dictionary[keyToFindInDictionary]);
  8.     }
  9.     catch (KeyNotFoundException)
  10.     {
  11.         // fallback
  12.     }
  13. }
  14.  
  15. private void DoSomethingWithTheResult(string s)
  16. {
  17.     // do something
  18. }

As you can see he catches the exception to handle the fact that the given key was not found in the dictionary.

I told him that there was a better way, i.e. Dictionary<TKey, TValue>.TryGetValue.

And then the curious part of me started thinking, how much better is it? Is it faster? Slower?

So I wrote the following small piece of code to test my statement that TryGetValue is better than catching the KeyNotFoundException.

  1. namespace DictionaryTryGetValueVersusException
  2. {
  3.     using System;
  4.     using System.Collections.Generic;
  5.     using System.Diagnostics;
  6.  
  7.     internal class Program
  8.     {
  9.         private static void Main()
  10.         {
  11.             // create a dictionary with some values
  12.             Dictionary<string, string> dictionary = new Dictionary<string, string>();
  13.  
  14.             // add 10,000 items
  15.             for (int i = 0; i < 10000; i++)
  16.             {
  17.                 if (i == 5000)
  18.                 {
  19.                     // skip
  20.                     continue;
  21.                 }
  22.  
  23.                 dictionary.Add(string.Format("Key{0}", i), string.Format("Value{0}", i));
  24.             }
  25.  
  26.             Stopwatch stopwatch = new Stopwatch();
  27.  
  28.             stopwatch.Start();
  29.  
  30.             const string keyToFindInDictionary = "Key5000";
  31.  
  32.             for (int i = 0; i < 10000; i++)
  33.             {
  34.                 // 5000 does not exist
  35.                 try
  36.                 {
  37.                     // execute a method on the variable, so that he compiler doesn't optimize it.
  38.                     dictionary[keyToFindInDictionary];
  39.                 }
  40.                 catch (Exception)
  41.                 {
  42.                     // ignore
  43.                 }
  44.             }
  45.  
  46.             stopwatch.Stop();
  47.             Console.WriteLine("Dictionary lookup with try/catch took: {0}", stopwatch.ElapsedTicks);
  48.  
  49.             stopwatch.Restart();
  50.  
  51.             for (int i = 0; i < 10000; i++)
  52.             {
  53.                 string notFound;
  54.                 // 5000 does not exist
  55.                 dictionary.TryGetValue(keyToFindInDictionary, out notFound);
  56.             }
  57.  
  58.             stopwatch.Stop();
  59.             Console.WriteLine("Dictionary lookup with TryGetValue took: {0}", stopwatch.ElapsedTicks);
  60.  
  61.             Console.WriteLine("Done, press enter to exit");
  62.             Console.ReadLine();
  63.         }
  64.     }
  65. }

As you can see we add 10,000 items to the dictionary, skipping the 5000th item, and then we do a lookup in the dictionary, 10,000 times, on the key that doesn’t exist, to measure the performance difference between the 2 previously discussed methods.

To run this test I did a Release Build in Visual Studio 2010, .NET 4.0, Any CPU, and this is the result:

Results

Dictionary lookup with try/catch took: 1069625
Dictionary lookup with TryGetValue took: 864
Done, press enter to exit

As you can see there is a HUGE difference. The TryGetValue-way was about 1237 faster!

Exception throwing is very heavy! Don’t forget that. It doesn’t mean that you need to program without exceptions, but when you EXPECT that a Key is not present in a given dictionary, don’t use the exception. Use the TryGetValue. If you always expect it to be there then it’s normal to catch the exception, because it’s exceptional that the key was not found.

PS: I tried the code again by skipping the 9999th item, and the results were about the same, take or leave a few milliseconds. So searching in the dictionary is very performant (close to O(1), as written in the Remarks section on this page.)

Windows Phone 7 TextBox, binding and ApplicationButton

Consider a Windows Phone 7 application with a textbox and an ApplicationButton.

TextBox and ApplicationButton

UI:

  1. <Canvas x:Name="ContentGrid" Grid.Row="1" Height="545" Width="480">
  2.     <TextBlock Text="Enter text here" Canvas.Left="6" Canvas.Top="187" />
  3.     <TextBox x:Name="myTextBox" Text="{Binding Test, Mode=TwoWay}" Height="69" Width="480" Canvas.Left="0" Canvas.Top="209" />
  4. </Canvas>

Backend:

  1. namespace WindowsPhoneApplication1
  2. {
  3.     using System;
  4.     using System.ComponentModel;
  5.     using System.Windows.Controls;
  6.     using Microsoft.Phone.Controls;
  7.  
  8.     public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
  9.     {
  10.         private string _test;
  11.         // Constructor
  12.         public MainPage()
  13.         {
  14.             this.InitializeComponent();
  15.  
  16.             this.DataContext = this;
  17.         }
  18.  
  19.         public string Test
  20.         {
  21.             get
  22.             {
  23.                 return this._test;
  24.             }
  25.             set
  26.             {
  27.                 if (value != this._test)
  28.                 {
  29.                     this._test = value;
  30.                     this.PropertyChanged(this, new PropertyChangedEventArgs("Test"));
  31.                 }
  32.             }
  33.         }
  34.  
  35.         #region INotifyPropertyChanged Members
  36.  
  37.         public event PropertyChangedEventHandler PropertyChanged;
  38.  
  39.         #endregion
  40.  
  41.     }
  42. }

The textbox is bound to a property on the backend (two way binding) and when you click the bottom button the text is saved/send/encrypted/whatever.

Now the problem is that clicking the button doesn’t do a UI –> source binding update as it would do with a normal button.

Testing the app

I enter the text ‘test’ on the TextBlock and IMMIDIATLY click the ApplicationButton. I don’t do anything else. This is a common user practice, he changes something and clicks the save/send/whatsoever button.

This is the result:

Visual Studio 2010 Watch 1

Check the Watch 1. As you can see the value is still null. The value is not sent to the _test value. How do we solve this?

You can add the following line to the click event handler:

  1. this.myTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();

So the result will look like this:

  1. private void AppbarButton1Click(object sender, EventArgs e)
  2. {
  3.     this.myTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
  4.  
  5.     // handle save/send/encrypt/whatever here
  6. }

There are 3 downsides I think:

  1. You need to name your TextBlock which (I think) unnecessarily clutters your scope with otherwise unused variables (that’s why we use bindings too!)
  2. Your UI and ViewModel (in my case) aren’t decoupled 100% anymore. In Windows Phone 7 this is no issue though, since WP7 has no ICommand and I have to couply my UI and ViewModel anyway :)
  3. You need to remember to write this line! Which can be quite cumbersome with a lot of application buttons.

And items in a ApplicationBar.MenuItems (ApplicationBarMenuItem) have the same problem. The UI doesn’t push the update to the ViewModel.

I hope this will be fixed in the final version, and I will post this to Microsoft Connect. If anybody has a better solution please feel free to share it.

A more general INotifyPropertyChangedHandler extension method for strongly typed reflection

  1. static class ExtensionMethods
  2. {
  3.     public static void Raise<TValue>(this PropertyChangedEventHandler handler, Expression<Func<TValue>> propertySelector)
  4.     {
  5.         var memberExpression = propertySelector.Body as MemberExpression;
  6.  
  7.         if (handler == null || memberExpression == null)
  8.         {
  9.             return;
  10.         }
  11.  
  12.         var sender = ((ConstantExpression)memberExpression.Expression).Value;
  13.         handler(sender, new PropertyChangedEventArgs(memberExpression.Member.Name));
  14.     }
  15. }

Use this as an extension method like this on a class that implements INotifyPropertyChanged

  1. class SomeClass : INotifyPropertyChanged
  2. {
  3.     private string _someProperty;
  4.  
  5.     public string SomeProperty
  6.     {
  7.         get
  8.         {
  9.             return this._someProperty;
  10.         }
  11.         set
  12.         {
  13.             if (value != this._someProperty)
  14.             {
  15.                 this._someProperty = value;
  16.                 this.PropertyChanged.Raise(() => this.SomeProperty);
  17.             }
  18.         }
  19.     }
  20.  
  21.     public event PropertyChangedEventHandler PropertyChanged;
  22. }

Good luck :)

-Kristof

MvvmLight: strongly typed INotifyPropertyChanged

Since MvvmLight exposes it’s own ViewModelBase you cannot use this little script to raise the INotifyPropertyChangedEventHandler, because .NET doesn’t allow you to raise events in derived classes. This is because the compiler generates a private delegate (it’s in VB.NET but that doesn’t matter).

And since the ViewModelBase only exposes a protected RaiseProperty(string propertyName) I cannot use strongly typed reflection.

So I found some code, and rewrote it like this.

Now you can create a class that inherits from ViewModelBase, and make your ViewModels inherit from your just created class.

Now you have a pattern like this:

ViewModelBase <—DefaultViewModel <—MainPageViewModel

And your DefaultViewModel should look like this:

  1. public abstract class DefaultViewModel : ViewModelBase
  2. {
  3.     protected void RaisePropertyChanged<TValue>(Expression<Func<TValue>> propertySelector)
  4.     {
  5.         var memberExpression = (propertySelector.Body as MemberExpression);
  6.  
  7.         if (null != memberExpression)
  8.         this.RaisePropertyChanged(memberExpression.Member.Name);
  9.     }
  10. }

And your MainPageViewModel (for example):

  1. public class MainPageViewModel : DefaultViewModel
  2. {
  3.     private decimal _remainingCredits;
  4.  
  5.     /// <summary>
  6.     /// Remaining credits of the current account
  7.     /// </summary>
  8.     public decimal RemainingCredits
  9.     {
  10.         get
  11.         {
  12.             return this._remainingCredits;
  13.         }
  14.  
  15.         set
  16.         {
  17.             if (this._remainingCredits != value)
  18.             {
  19.                 this._remainingCredits = value;
  20.  
  21.                 this.RaisePropertyChanged(() => RemainingCredits);
  22.             }
  23.         }
  24.     }
  25. }

You can use the form of RaisePropertyChanged(() => NameOfProperty);

This way, when you rename a variable in your code the refactor engine picks it up and renames it accordingly. (it forget strings :)

Good luck,

Kristof

Windows Phone 7, adding and displaying icons.

Hi all,

I tried to display an icon in my Windows Phone 7 application:

<shell:ApplicationBarIconButton x:Name="appbar_button1" IconUri="/Images/appbar.feature.settings.rest.png" Text="Settings" />

By default, when you add an image to the solution folder it sets the build action as Resource, as shown below:

Build Action Resource

But when you run the application with the Build Action as Resource you will get a result looking like this:

Wrong icon

While I really meant an icon looking like this:

Gear

How do we fix it?

Set the Build Action to Content!

Build Action Content

And this is the result:

Result

Silverlight 4 debugging and Firefox 3.6.4+

I’ve been stuck on this for a few days.

At the moment, Firefox 3.6.4 (and newer) have a new functionality called ‘Crash protection’, which is quite nice.

For customers.

It now runs the plugins in a separate process called ‘plugin-container.exe’ (look in your task manager).

Task manager plugin-container.exe

But for developers it’s quite the hassle, since Visual Studio attaches itself to Firefox but NOT to this process. So no more Silverlight debugging for you!

Luckily there are two options for you!

The first option is the most straight forward, but has to be done each time. Use Visual Studio to attach itself to plugin-container.exe, refresh the website, and BAM, you’re up and running!

Attach to Process

On the next screen click ‘plugin-container.exe’. There might be 2, if so, select the one with ‘Silverlight’ in the ‘Type’ column:

Attach to Process Window

And hit ‘Attach’.

While this solution is adequate for when you need to debug it one time at a day, but for me, I only debug in Firefox, and when necessary I use Internet Explorer. For that you can go to your ‘about:config’ in Firefox, disable ‘dom.ipc.plugins.enabled.npctrl.dll’ (set it to false).

Property setters and side effects

I ran into this little problem last week. I had a class with some properties and they were implemented like this:

class Foo
{
    private int _bar;

    public int Bar
    {
        get
        {
            return this._bar;
        }
        set
        {
            this._bar = value;
            this.DoSomeThing();
        }
    }

    private void DoSomeThing()
    {
        /* blah */
    }
}

Setting the value of Bar to something triggers DoSomeThing, whether the value of _bar is changed or not. (setting _bar to 5 when it is 5 will still trigger DoSomeThing, for example a UI refresh).

You can avoid this by doing this in your property:

class Foo
{
    private int _bar;

    public int Bar
    {
        get
        {
            return this._bar;
        }
        set
        {
            if (this._bar != value)
            {
                this._bar = value;
                DoSomeThing();
            }
        }
    }

    private void DoSomeThing()
    {
        /* blah */
    }
}

This makes sure that you don’t execute the value when the value hasn’t changed.

This occurs in particular in Excel when trying to update the CurrentPageName of a DataField in a PivotTable. I need to check if the value has changed, and then, if it has changed, assign it.

Dispose and Finalizing, done the right way

I created this class to make life a little bit easier for me.

You are free to use it as you wish!

How to use:

Override this class, override ReleaseManaged() and ReleaseUnmanaged() with the appropriate code, and you are good to go.

namespace SuperDisposeImplementation
{
    using System;

    /// <summary>
    /// Override this class for easy releasing of managed and unmanaged code.
    /// </summary>
    /// <remarks>
    /// By Kristof Mattei
    /// Use as you wish
    /// I don't hold the copyright
    /// Combined from code I found everywhere.
    /// </remarks>
    public abstract class SuperDispose : IDisposable
    {
        /// <summary>
        /// True if managed resources are already cleaned up, false if not
        /// </summary>
        private bool _disposed;

        #region IDisposable Members

        /// <summary>
        /// Implementation of IDisposable.Dispose(). Don't make virtual
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        #endregion

        /// <summary>
        /// Dispose(bool disposing) executes in two distinct scenarios.
        /// If disposing equals true, the method has been called directly
        /// or indirectly by a user's code. Managed and unmanaged resources
        /// can be disposed.
        /// If disposing equals false, the method has been called by the
        /// runtime from inside the finalizer and you should not reference
        /// other objects. Only unmanaged resources can be disposed.
        /// </summary>
        /// <param name="disposing">True when called from the Dispose, false when called from the ~. Don't call yourself</param>
        private void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this._disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                {
                    this.ReleaseManaged();
                }

                // Dispose unmanaged resources.
                this.ReleaseUnmanaged();

                // disposing has been done, make sure we don't dispose the managed ones again.
                this._disposed = true;
            }
        }

        /// <summary>
        /// Override this method, and release unmanaged resources in that method
        /// </summary>
        protected abstract void ReleaseUnmanaged();

        /// <summary>
        /// Override this method, and release managed resources in that method
        /// </summary>
        protected abstract void ReleaseManaged();

        /// <summary>
        /// Use C# destructor syntax for finalization code.
        /// This destructor will run only if the Dispose method
        /// does not get called.
        /// It gives your base class the opportunity to finalize.
        /// Do not provide destructors in types derived from this class.
        /// </summary>
        ~SuperDispose()
        {
            // make sure we don't dispose managed resources, hence the false
            // this is because we can't control the called order of
            this.Dispose(false);
        }
    }
}