Numpad’s decimal-point correction for WPF

numpadJust a quick-and-dirty solution for solving the tedious problem of the numpad’s decimal-point insertion where the culture require something different than a dot “.”.

The problem.

Many of you, who aren’t using a dot as decimal separator, maybe noticed that the character issued by the numeric-pad is always a doe, regardless the OS settings. In Italy, for instance, we’re using the comma as decimal separator.
You know, if you type the wrong character, the number won’t be recognized as valid (sometimes even worse, because it’s mistaken as valid).
If you try to open Notepad or any raw-input application, you’ll notice that there’s no way to “hack” the Windows settings in order to correctly input the numeric-pad “point” as a comma. By the way, if you enter a number in Microsoft Excel or so, the character is actually a comma.
Looks like the translation is something managed by the application.

It’s not so simple, though.
Imagine to write your own application (WPF in my case), and have a series of textboxes. Whereas a textbox used for entering a number (e.g. most physical units) would be fine having a “translation” to a comma, when another textbox used for an IP-pattern, clearly should *NOT* be translated any time.
Looks like that some countries use a different punctuation for generic numbers and for currency: my “neighbor” friends of Switzerland do use the comma for any number but currency, where the dot is preferred.

The solution.

Here is a solution, but I believe is difficult to satisfy all the developers’ habits. I just opted for a simple attached-property, as “behavior” to any TextBoxBase object, which “intercepts” the Decimal key (the numpad’s DP) and replaces it with the proper one.

namespace DecimalPointCorrectorDemo
{
    public enum DecimalPointCorrectionMode
    {
        /// <summary>
        /// (Default) No correction is applied, and any style
        /// inherited setting may influence the correction behavior.
        /// </summary>
        Inherits,

        /// <summary>
        /// Enable the decimal-point correction for generic numbers.
        /// </summary>
        Number,

        /// <summary>
        /// Enable the decimal-point correction for currency numbers.
        /// </summary>
        Currency,

        /// <summary>
        /// Enable the decimal-point correction for percent-numbers.
        /// </summary>
        Percent,
    }


    /// <summary>
    /// General purpose container for <see cref="System.Windows.Controls.TextBox"/> helpers.
    /// </summary>
    public static class TextBoxHelper
    {

        #region DPA DecimalPointCorrection

        public static readonly DependencyProperty DecimalPointCorrectionProperty = DependencyProperty.RegisterAttached(
            "DecimalPointCorrection",
            typeof(DecimalPointCorrectionMode),
            typeof(TextBoxHelper),
            new UIPropertyMetadata(
                default(DecimalPointCorrectionMode),
                DecimalPointCorrectionChanged
                ));


        public static DecimalPointCorrectionMode GetDecimalPointCorrection(TextBoxBase obj)
        {
            return (DecimalPointCorrectionMode)obj.GetValue(DecimalPointCorrectionProperty);
        }


        public static void SetDecimalPointCorrection(TextBoxBase obj, DecimalPointCorrectionMode value)
        {
            obj.SetValue(DecimalPointCorrectionProperty, value);
        }

        #endregion


        private static void DecimalPointCorrectionChanged(
            object sender,
            DependencyPropertyChangedEventArgs args
            )
        {
            var tbox = (TextBoxBase)sender;

            //remove any existent event subscription
            switch ((DecimalPointCorrectionMode)args.OldValue)
            {
                case DecimalPointCorrectionMode.Number:
                case DecimalPointCorrectionMode.Currency:
                case DecimalPointCorrectionMode.Percent:
                    tbox.PreviewKeyDown -= tbox_PreviewKeyDown;
                    break;
            }

            //subscribe the event handler, whereas necessary
            switch ((DecimalPointCorrectionMode)args.NewValue)
            {
                case DecimalPointCorrectionMode.Number:
                case DecimalPointCorrectionMode.Currency:
                case DecimalPointCorrectionMode.Percent:
                    tbox.PreviewKeyDown += tbox_PreviewKeyDown;
                    break;
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void tbox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            //filter the numpad's decimal-point key only
            if (e.Key == System.Windows.Input.Key.Decimal)
            {
                //mark the event as handled, so no further action will take place
                e.Handled = true;

                //grab the originating texbox control...
                var tbox = (TextBoxBase)sender;

                //the current correction mode...
                var mode = TextBoxHelper.GetDecimalPointCorrection(tbox);

                //and the culture of the thread involved (UI)
                var culture = Thread.CurrentThread.CurrentCulture;

                //surrogate the blocked key pressed
                SimulateDecimalPointKeyPress(
                    tbox, 
                    mode, 
                    culture
                    );
            }
        }


        /// <summary>
        /// Insertion of the proper decimal-point as part of the textbox content
        /// </summary>
        /// <param name="tbox"></param>
        /// <param name="mode"></param>
        /// <param name="culture"></param>
        /// <remarks>
        /// Typical "async-void" pattern as "fire-and-forget" behavior.
        /// </remarks>
        private static async void SimulateDecimalPointKeyPress(
            TextBoxBase tbox,
            DecimalPointCorrectionMode mode,
            CultureInfo culture
            )
        {
            //select the proper decimal-point string upon the context
            string replace;
            switch (mode)
            {
                case DecimalPointCorrectionMode.Number:
                    replace = culture.NumberFormat.NumberDecimalSeparator;
                    break;

                case DecimalPointCorrectionMode.Currency:
                    replace = culture.NumberFormat.CurrencyDecimalSeparator;
                    break;

                case DecimalPointCorrectionMode.Percent:
                    replace = culture.NumberFormat.PercentDecimalSeparator;
                    break;

                default:
                    replace = null;
                    break;
            }

            if (string.IsNullOrEmpty(replace) == false)
            {
                //insert the desired string
                var tc = new TextComposition(
                    InputManager.Current,
                    tbox,
                    replace
                    );

                TextCompositionManager.StartComposition(tc);
            }

            await Task.FromResult(false);
        }

    }
}

The code is rather simple, so I think would be useless chatting more.
The only worthwhile point is regarding the “async” pattern in the key-replace function. I just wanted to leave the originating event (PreviewKeyDown) a bit of time to finish before adding another (possible) event. Honestly, I don’t know whether that’s really necessary: the async-await pattern comes easy and reliable, so I prefer to keep the code safer. Feel free to improve the it.

correction-off

correction-on

The complete demo solution source code can be downloaded here.

This code has been tested widely enough, including on the Windows 8 on-screen touch-keyboard.
Enjoy!

A WPF StackPanel-surrogate with shared-sizing scope ability

Here is a simple trick for simulating the shared-sizing feature of the WPF Grid even in a StackPanel fashion.

demo

Basically, you can have several panels, each one in a separate visual fragment, and “synchronize” their children height (or width, when horizontally-oriented).
A short video explains better than thousands of words.

The solution is pretty simple. Since the Grid already offers such a feature, the trick is leveraging it instead a “real” StackPanel. Otherwise, the mechanism for managing the shared-size scopes is rather complex. As for “complex” I mean that you should keep all the scrolling and virtualization features which is part of a StackPanel, and that’s rather complex.
The resulting StackPanel-surrogate code is very simple:

    /// <summary>
    /// Represent a StackPanel surrogate whose children width/height can be
    /// shared with other homogeneous panel's children
    /// </summary>
    public class StackPanel3S
        : Grid
    {
        /// <summary>
        /// Gets or sets a value that identifies the panel as a member 
        /// of a defined group that shares sizing properties.
        /// </summary>
        public string SharedSizeGroup { get; set; }


        #region DP Orientation

        /// <summary>
        /// Identifies the StackPanelEx.Orientation dependency property.
        /// </summary>
        public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
            "Orientation",
            typeof(Orientation),
            typeof(StackPanel3S),
            new FrameworkPropertyMetadata(
                Orientation.Vertical,
                FrameworkPropertyMetadataOptions.AffectsMeasure,
                (obj, args) =>
                {
                    var ctl = (StackPanel3S)obj;
                    ctl.OrientationChanged(args);
                }));


        /// <summary>
        /// Gets or sets a value that indicates the dimension by which child elements are stacked.
        /// </summary>
        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        #endregion


        private void OrientationChanged(
            DependencyPropertyChangedEventArgs args
            )
        {
            //flush any current row/column definition
            this.RowDefinitions.Clear();
            this.ColumnDefinitions.Clear();
        }


        protected override Size MeasureOverride(Size constraint)
        {
            //retrieve the number of children
            int count = this.InternalChildren.Count;

            if (this.Orientation == System.Windows.Controls.Orientation.Vertical)
            {
                //add the missing row-defintions
                for (int i = this.RowDefinitions.Count; i < count; i++)
                {
                    this.RowDefinitions.Add(
                        new RowDefinition()
                        {
                            Height = GridLength.Auto,
                            SharedSizeGroup = this.SharedSizeGroup + "__R" + i
                        });
                }

                //remove the unnecessary row-definitions
                for (int i = this.RowDefinitions.Count - 1; i >= count; i--)
                {
                    this.RowDefinitions.RemoveAt(i);
                }

                //assing a progressive index to each child
                for (int i = 0; i < count; i++)
                {
                    UIElement child;
                    if ((child = this.InternalChildren[i]) != null)
                    {
                        Grid.SetRow(child, i);
                    }
                }
            }
            else
            {
                //add the missing column-defintions
                for (int i = this.ColumnDefinitions.Count; i < count; i++)
                {
                    this.ColumnDefinitions.Add(
                        new ColumnDefinition()
                        {
                            Width = GridLength.Auto,
                            SharedSizeGroup = this.SharedSizeGroup + "__C" + i
                        });
                }

                //remove the unnecessary column-definitions
                for (int i = this.ColumnDefinitions.Count - 1; i >= count; i--)
                {
                    this.ColumnDefinitions.RemoveAt(i);
                }

                //assing a progressive index to each child
                for (int i = 0; i < count; i++)
                {
                    UIElement child;
                    if ((child = this.InternalChildren[i]) != null)
                    {
                        Grid.SetColumn(child, i);
                    }
                }
            }

            //yield the default measuring pass
            return base.MeasureOverride(constraint);
        }

    }

Enjoy!

Nesting a private C# Dynamic object

I don’t use often the dynamic feature of the C# language, but past yesterday I bumped against a subtle issue.

A basic implementation.

Consider a very basic dynamic object implementation against the DynamicObject, which looks like the overhauled ExpandoObject:

    public class MyDynamicObject
        : DynamicObject
    {
        public MyDynamicObject()
        {
            this._dict = new Dictionary<string, object>();
        }


        private readonly Dictionary<string, object> _dict;


        /**
         * called when the host tries to GET the value
         * from a member
         **/
        public override bool TryGetMember(
            GetMemberBinder binder,
            out object result
            )
        {
            //look for the member into the dictionary
            bool found = this._dict.TryGetValue(
                binder.Name,
                out result
                );

            if (found)
            {
                return true;
            }

            //yield the default behavior
            return base.TryGetMember(
                binder,
                out result
                );
        }


        /**
         * called when the host tries to SET a value
         * against a member
         **/
        public override bool TrySetMember(
            SetMemberBinder binder,
            object value
            )
        {
            //store the value in the dictionary
            this._dict[binder.Name] = value;
            return true;
        }

    }

Its usage may be expressed as follows:

    class Program
    {
        static void Main(string[] args)
        {
            dynamic d = new MyDynamicObject();
            d.first = "John";
            d.last = "Doe";
            d.birthdate = new DateTime(1966, 7, 23);
            d.registered = true;

            Console.WriteLine(d.first);
            Console.WriteLine(d.last);
            Console.WriteLine(d.birthdate);
            Console.WriteLine(d.registered);

            Console.ReadKey();
        }
    }

So far, so well. But what about retrieving a member “by name”, that is using a string as a “key” for mapping the desired member?
The above snippet could be refined as follows:

    class Program
    {
        static void Main(string[] args)
        {
            dynamic d = new MyDynamicObject();
            d.first = "John";
            d.last = "Doe";
            d.birthdate = new DateTime(1966, 7, 23);
            d.registered = true;

            Console.WriteLine(d.first);
            Console.WriteLine(d.last);
            Console.WriteLine(d.birthdate);
            Console.WriteLine(d.registered);

            Console.WriteLine();
            Console.Write("Please enter a field name: ");
            string key = Console.ReadLine();

            //how to map the required field?
            //Console.WriteLine("The field value is: " + ??? );

            Console.ReadKey();
        }
    }

Again, with an ExpandoObject everything would be straightforward, but the actual “MyDynamicObject” used in the original application requires a more complex content, with XML and a dictionary working aside.

pic1

Going on this way, the “keyed” dynamic object implementation is easy to refine:

    public class MyDynamicObject
        : DynamicObject
    {

        // ... original implementation ...


        /**
         * provide a member access through a key
         **/
        public object this[string key]
        {
            get { return this._dict[key]; }
            set { this._dict[key] = value; }
        }

    }

At this point, the demo application works fine with both the accessing way. It looks much like a JavaScript object!

    class Program
    {
        static void Main(string[] args)
        {
            dynamic d = new MyDynamicObject();
            d.first = "John";
            d.last = "Doe";
            d.birthdate = new DateTime(1966, 7, 23);
            d["registered"] = true;

            Console.WriteLine(d.first);
            Console.WriteLine(d.last);
            Console.WriteLine(d.birthdate);
            Console.WriteLine(d.registered);

            Console.WriteLine();
            Console.Write("Please enter a field name: ");
            string key = Console.ReadLine();

            Console.WriteLine("The field value is: " + d[key]);
            Console.ReadKey();
        }
    }

pic2

The problem: a nested-private dynamic object.

Consider a proxy pattern, and a dynamic object to expose indirectly to the hosting application. Also consider that the dynamic object should be marked as “private” due to avoid any possible usage outside its context.
The revised component would look as follows:

    class MyClass
    {

        public IDynamicMetaObjectProvider GetDynamicAccess()
        {
            return new MyDynamicObject();
        }


        //notice that the below class is marked as "private"
        private class MyDynamicObject
            : DynamicObject
        {

            // ... implementation as the keyed-one seen above ...

        }
    }

When used in such a sample application, it won’t work:

    class Program
    {
        static void Main(string[] args)
        {
            var c = new MyClass();

            dynamic d = c.GetDynamicAccess();
            d.first = "John";
            d.last = "Doe";
            d.birthdate = new DateTime(1966, 7, 23);
            d["registered"] = true;     //throws!

            Console.WriteLine(d.first);
            Console.WriteLine(d.last);
            Console.WriteLine(d.birthdate);
            Console.WriteLine(d.registered);

            Console.WriteLine();
            Console.Write("Please enter a field name: ");
            string key = Console.ReadLine();

            //the following would also throw
            Console.WriteLine("The field value is: " + d[key]);
            Console.ReadKey();
        }
    }

Better: it won’t work the “keyed” access, but the classic way is available, however.

I wasn’t able to find *ANY* solution unless you have the ability to modify the implementation. Here are the possible solutions.

Solution 1: mark the MyDynamicObject class accessor as “public”.

This is the simplest way, but I’d say it’s also a NON-solution because the original desire is keeping the class as “private”.

Solution 2: use the reflection.

You know, reflection is able to dig into the deepest yet hidden corners of your assembly, but it’s yet a last-rescue way. The compiler has a very-little (or nothing at all) control over what we access through reflection. I’d discourage, though feasible.

Solution 3: add an interface.

The “best” solution (although I’d demote to “decent”) is adding an interface, which aim is to expose the indexed access (keyed) to the host application.

    interface IKeyedAccess
    {
        object this[string name] { get; set; }
    }


    class MyClass
    {

        public IDynamicMetaObjectProvider GetDynamicAccess()
        {
            return new MyDynamicObject();
        }


        //notice that the below class is marked as "private"
        private class MyDynamicObject
            : DynamicObject, IKeyedAccess
        {

            // ... implementation as the keyed-one seen above ...

        }
    }

Our keyed-dynamic object must implement the interface, but rather obvious because our primary goal is that.
The major difference is rather on the object usage:

    class Program
    {
        static void Main(string[] args)
        {
            var c = new MyClass();

            dynamic d = c.GetDynamicAccess();
            var dk = (IKeyedAccess)d;
            d.first = "John";
            d.last = "Doe";
            d.birthdate = new DateTime(1966, 7, 23);
            dk["registered"] = true;

            Console.WriteLine(d.first);
            Console.WriteLine(d.last);
            Console.WriteLine(d.birthdate);
            Console.WriteLine(d.registered);

            Console.WriteLine();
            Console.Write("Please enter a field name: ");
            string key = Console.ReadLine();

            Console.WriteLine("The field value is: " + dk[key]);
            Console.ReadKey();
        }
    }

Unfortunately not as good as expected, but at least it allows to keep sticky to the “private” constraint.

Here is the source code.

Which is better?

Just a quick post on how to write “better” a small piece of code.
First off, “better” is ambiguous: it should mean “elegant”, or “readable”? Maybe “performing” or even “compact”? In general, I tend to favor the readability, for a better maintenance; whereas possible a good performance as well.
Secondly, although this case is against the .Net Micro Framework (where the resources are very poor), the considerations may be applied for any platform. Here the discussion is focused just on the IL: not more in depth.
Last but lot least, the language is C#. Plain and safe C#: pointer tricks are not allowed at all.

The problem.

The problem depicted here is just an example. The goal is to store an Int16 value (16-bits wide signed integer) onto a byte-array, at a certain offset, using the Little-Endian format. It’s clear that it could be used any kind of integer, and also a different format.
As for example, given:

  • N = 12345 (0x3039 in Hex), as the value to store;
  • K = 23 (0x17 in Hex), as the starting offset of the array

The aim is storing N in the array as follows:

K K+1
Offset: 21 22 23 24 25 20
Content: x x 0x39 0x30 x x

Many ways to do it: which is better?

I found four different ways to solve the problem, but new versions are welcome.

The first is perhaps the most intuitive. I think there’s nothing to explain.

        private static void Test1(short value)
        {
            _buffer[_ptr++] = (byte)value;
            _buffer[_ptr++] = (byte)(value >> 8);
        }

The second way is a revised version of the first one, just because the post-increment is typically less compact yet performing than the pre-increment.

        private static void Test2(short value)
        {
            _buffer[_ptr] = (byte)value;
            _buffer[++_ptr] = (byte)(value >> 8);
            ++_ptr;
        }

The third way looks as the dumbest one: instead updating the offset on every step, just calculate the actual cell index. At the end, the global offset is updated once only.

        private static void Test3(short value)
        {
            _buffer[_ptr] = (byte)value;
            _buffer[_ptr + 1] = (byte)(value >> 8);
            _ptr += 2;
        }

The fourth looks as a file corruption, because it seems having no sense. Hard to read, hard to understand what the program does, and even if what id does, does it correctly. Always reliable?…hum…
However, there’s an explanation for this code further.

        private static void Test4(short value)
        {
            _buffer[_ptr] = (byte)(value + 0 * (_buffer[(_ptr += 2) - 1] = (byte)(value >> 8)));
        }

The results.

The comparison of the four snippets is relative to the speed of execution, but also on the compactness.
The execution template looks as follows:

            const int num = 10000000;
            const short k = 12345;
            Stopwatch sw;

            sw = Stopwatch.StartNew();
            for (int i = 0; i < num; i++)
            {
                _ptr = 0;
                Test1(k);
                Test1(k);
                Test1(k);
                Test1(k);
                Test1(k);
                Test1(k);
                Test1(k);
                Test1(k);
                Test1(k);
                Test1(k);
            }

            sw.Stop();
            Console.WriteLine("Test1=" + sw.ElapsedMilliseconds);

Here are the IL dump of the various snippets:

        private static void Test1(short value)
        {
            _buffer[_ptr++] = (byte)value;
            _buffer[_ptr++] = (byte)(value >> 8);
        }
	IL_0000: ldsfld uint8[] ConsoleApplication1.Program::_buffer
	IL_0005: ldsfld int32 ConsoleApplication1.Program::_ptr
	IL_000a: dup
	IL_000b: ldc.i4.1
	IL_000c: add
	IL_000d: stsfld int32 ConsoleApplication1.Program::_ptr
	IL_0012: ldarg.0
	IL_0013: conv.u1
	IL_0014: stelem.i1
	IL_0015: ldsfld uint8[] ConsoleApplication1.Program::_buffer
	IL_001a: ldsfld int32 ConsoleApplication1.Program::_ptr
	IL_001f: dup
	IL_0020: ldc.i4.1
	IL_0021: add
	IL_0022: stsfld int32 ConsoleApplication1.Program::_ptr
	IL_0027: ldarg.0
	IL_0028: ldc.i4.8
	IL_0029: shr
	IL_002a: conv.u1
	IL_002b: stelem.i1
	IL_002c: ret

        private static void Test2(short value)
        {
            _buffer[_ptr] = (byte)value;
            _buffer[++_ptr] = (byte)(value >> 8);
            ++_ptr;
        }
	IL_0000: ldsfld uint8[] ConsoleApplication1.Program::_buffer
	IL_0005: ldsfld int32 ConsoleApplication1.Program::_ptr
	IL_000a: ldarg.0
	IL_000b: conv.u1
	IL_000c: stelem.i1
	IL_000d: ldsfld uint8[] ConsoleApplication1.Program::_buffer
	IL_0012: ldsfld int32 ConsoleApplication1.Program::_ptr
	IL_0017: ldc.i4.1
	IL_0018: add
	IL_0019: dup
	IL_001a: stsfld int32 ConsoleApplication1.Program::_ptr
	IL_001f: ldarg.0
	IL_0020: ldc.i4.8
	IL_0021: shr
	IL_0022: conv.u1
	IL_0023: stelem.i1
	IL_0024: ldsfld int32 ConsoleApplication1.Program::_ptr
	IL_0029: ldc.i4.1
	IL_002a: add
	IL_002b: stsfld int32 ConsoleApplication1.Program::_ptr
	IL_0030: ret

        private static void Test3(short value)
        {
            _buffer[_ptr] = (byte)value;
            _buffer[_ptr + 1] = (byte)(value >> 8);
            _ptr += 2;
        }
	IL_0000: ldsfld uint8[] ConsoleApplication1.Program::_buffer
	IL_0005: ldsfld int32 ConsoleApplication1.Program::_ptr
	IL_000a: ldarg.0
	IL_000b: conv.u1
	IL_000c: stelem.i1
	IL_000d: ldsfld uint8[] ConsoleApplication1.Program::_buffer
	IL_0012: ldsfld int32 ConsoleApplication1.Program::_ptr
	IL_0017: ldc.i4.1
	IL_0018: add
	IL_0019: ldarg.0
	IL_001a: ldc.i4.8
	IL_001b: shr
	IL_001c: conv.u1
	IL_001d: stelem.i1
	IL_001e: ldsfld int32 ConsoleApplication1.Program::_ptr
	IL_0023: ldc.i4.2
	IL_0024: add
	IL_0025: stsfld int32 ConsoleApplication1.Program::_ptr
	IL_002a: ret

        private static void Test4(short value)
        {
            _buffer[_ptr] = (byte)(value + 0 * (_buffer[(_ptr += 2) - 1] = (byte)(value >> 8)));
        }
	IL_0000: ldsfld uint8[] ConsoleApplication1.Program::_buffer
	IL_0005: ldsfld int32 ConsoleApplication1.Program::_ptr
	IL_000a: ldarg.0
	IL_000b: ldsfld uint8[] ConsoleApplication1.Program::_buffer
	IL_0010: ldsfld int32 ConsoleApplication1.Program::_ptr
	IL_0015: ldc.i4.2
	IL_0016: add
	IL_0017: dup
	IL_0018: stsfld int32 ConsoleApplication1.Program::_ptr
	IL_001d: ldc.i4.1
	IL_001e: sub
	IL_001f: ldarg.0
	IL_0020: ldc.i4.8
	IL_0021: shr
	IL_0022: conv.u1
	IL_0023: stelem.i1
	IL_0024: conv.u1
	IL_0025: stelem.i1
	IL_0026: ret

The real surprise is on the speed results (milliseconds):

Test1=1034
Test2=848
Test3=712
Test4=801

It is worthwhile to notice that:

  • the pre-increment yields a little bonus in performance, despite the less-readable code. Also notice there are five “_ptr” accesses vs four in the first snippet, but that seems running faster anyway.
  • Surprisingly, the “dumbest” way to write the code is also the best one: not just on the speed, but compactness and readability as well.
  • The fourth snippet was just a test on how to “force” a certain IL generation, and -yes- it is very compact. Despite this effort, the speed result isn’t gratifying at all. That’s the loser solution for sure.
  • The interesting thing in the firth snippet is the fake multiplication (by zero), which aims to “compress” the two assignments in a single row. I’m pleased to see how smart is the compiler: it discard the useless multiplication, but not its terms.

Conclusions.

Just a short lesson on how to writer the code better.
Most of the times, you don’t have to bump your head against the wall to find the best solution as it were in native languages like C/C++. That’s why I love C#!

Convert a jagged array into a 2D-array

Yesterday there was an interesting question on Stackoverflow:

If you have an array like string[][], what’s the smartest way to convert it to a regular multidimensional array like string[,] assuming the former array is rectangular (not jagged)?

Of course, we should define better what does mean “smartest”: more performing? more compact? more elegant?
Anyway, it was a nice challenge, as an exercise, try to find any alternative way to the “classic imperative” approach.

In the following analysis we will consider a source jagged array, rectangular, and having non-zero dimensions.
The source array is created and filled as follows:

            //example jagged array
            string[][] ja = new string[2][];

            for (int i = 0; i < 2; i++)
            {
                ja[i] = new string[3];

                for (int k = 0; k < 3; k++)
                {
                    ja[i][k] = "Cell [" + i + "," + k + "]";
                }
            }

The imperative way.

The imperative way is the most intuitive, I think.
The task is very simple as iterating throughout the first (outer) dimensions, then through the second (inner). That will yield the access to each cell of the 2D-matrix of the target array, but the source datum is easy to get as well.

        static string[,] ImperativeConvert(string[][] source)
        {
            string[,] result = new string[source.Length, source[0].Length];

            for (int i = 0; i < source.Length; i++)
            {
                for (int k = 0; k < source[0].Length; k++)
                {
                    result[i, k] = source[i][k];
                }
            }

            return result;
        }

What about the IL-code of the “Release” compilation?

	IL_0000: ldarg.0
	IL_0001: ldlen
	IL_0002: conv.i4
	IL_0003: ldarg.0
	IL_0004: ldc.i4.0
	IL_0005: ldelem.ref
	IL_0006: ldlen
	IL_0007: conv.i4
	IL_0008: newobj instance void string[0..., 0...]::.ctor(int32, int32)
	IL_000d: stloc.0
	IL_000e: ldc.i4.0
	IL_000f: stloc.1
	IL_0010: br.s IL_0033
	// loop start (head: IL_0033)
		IL_0012: ldc.i4.0
		IL_0013: stloc.2
		IL_0014: br.s IL_0027
		// loop start (head: IL_0027)
			IL_0016: ldloc.0
			IL_0017: ldloc.1
			IL_0018: ldloc.2
			IL_0019: ldarg.0
			IL_001a: ldloc.1
			IL_001b: ldelem.ref
			IL_001c: ldloc.2
			IL_001d: ldelem.ref
			IL_001e: call instance void string[0..., 0...]::Set(int32, int32, string)
			IL_0023: ldloc.2
			IL_0024: ldc.i4.1
			IL_0025: add
			IL_0026: stloc.2

			IL_0027: ldloc.2
			IL_0028: ldarg.0
			IL_0029: ldc.i4.0
			IL_002a: ldelem.ref
			IL_002b: ldlen
			IL_002c: conv.i4
			IL_002d: blt.s IL_0016
		// end loop

		IL_002f: ldloc.1
		IL_0030: ldc.i4.1
		IL_0031: add
		IL_0032: stloc.1

		IL_0033: ldloc.1
		IL_0034: ldarg.0
		IL_0035: ldlen
		IL_0036: conv.i4
		IL_0037: blt.s IL_0012
	// end loop

	IL_0039: ldloc.0
	IL_003a: ret

It’s not as simple as the original C#-code, but still readable (with an effort).

The declarative (Linq) way.

I found a declarative way by using Linq, and that’s working fine, but I myself having an effort for defining it as “smarter” than the first solution.

        static string[,] LinqConvert(string[][] source)
        {
            return new[] { new string[source.Length, source[0].Length] }
                .Select(_ => new { x = _, y = source.Select((a, ia) => a.Select((b, ib) => _[ia, ib] = b).Count()).Count() })
                .Select(_ => _.x)
                .First();
        }

Since the Linq is often considered an elegant way to perform some repetitive tasks, here the code is far from elegant yet readable. By the way, since the basic operation is an “action” (copy cells), that’s hitting against the Linq concept, which “pulls” data.
Anyway, the IL-code seems a bit more compact than before: that’s because the many calls, though.

	IL_0000: newobj instance void ConsoleApplication4.Program/'<>c__DisplayClass5'::.ctor()
	IL_0005: stloc.0
	IL_0006: ldloc.0
	IL_0007: ldarg.0
	IL_0008: stfld string[][] ConsoleApplication4.Program/'<>c__DisplayClass5'::source
	IL_000d: ldc.i4.1
	IL_000e: newarr string[0..., 0...]
	IL_0013: stloc.1
	IL_0014: ldloc.1
	IL_0015: ldc.i4.0
	IL_0016: ldloc.0
	IL_0017: ldfld string[][] ConsoleApplication4.Program/'<>c__DisplayClass5'::source
	IL_001c: ldlen
	IL_001d: conv.i4
	IL_001e: ldloc.0
	IL_001f: ldfld string[][] ConsoleApplication4.Program/'<>c__DisplayClass5'::source
	IL_0024: ldc.i4.0
	IL_0025: ldelem.ref
	IL_0026: ldlen
	IL_0027: conv.i4
	IL_0028: newobj instance void string[0..., 0...]::.ctor(int32, int32)
	IL_002d: stelem.ref
	IL_002e: ldloc.1
	IL_002f: ldloc.0
	IL_0030: ldftn instance class '<>f__AnonymousType0`2'<string[0..., 0...], int32> ConsoleApplication4.Program/'<>c__DisplayClass5'::'<LinqConvert>b__0'(string[0..., 0...])
	IL_0036: newobj instance void class [mscorlib]System.Func`2<string[0..., 0...], class '<>f__AnonymousType0`2'<string[0..., 0...], int32>>::.ctor(object, native int)
	IL_003b: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!1> [System.Core]System.Linq.Enumerable::Select<string[0..., 0...], class '<>f__AnonymousType0`2'<string[0..., 0...], int32>>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, !!1>)
	IL_0040: ldsfld class [mscorlib]System.Func`2<class '<>f__AnonymousType0`2'<string[0..., 0...], int32>, string[0..., 0...]> ConsoleApplication4.Program::'CS$<>9__CachedAnonymousMethodDelegate4'
	IL_0045: brtrue.s IL_0058

	IL_0047: ldnull
	IL_0048: ldftn string[0..., 0...] ConsoleApplication4.Program::'<LinqConvert>b__3'(class '<>f__AnonymousType0`2'<string[0..., 0...], int32>)
	IL_004e: newobj instance void class [mscorlib]System.Func`2<class '<>f__AnonymousType0`2'<string[0..., 0...], int32>, string[0..., 0...]>::.ctor(object, native int)
	IL_0053: stsfld class [mscorlib]System.Func`2<class '<>f__AnonymousType0`2'<string[0..., 0...], int32>, string[0..., 0...]> ConsoleApplication4.Program::'CS$<>9__CachedAnonymousMethodDelegate4'

	IL_0058: ldsfld class [mscorlib]System.Func`2<class '<>f__AnonymousType0`2'<string[0..., 0...], int32>, string[0..., 0...]> ConsoleApplication4.Program::'CS$<>9__CachedAnonymousMethodDelegate4'
	IL_005d: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!1> [System.Core]System.Linq.Enumerable::Select<class '<>f__AnonymousType0`2'<string[0..., 0...], int32>, string[0..., 0...]>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, !!1>)
	IL_0062: call !!0 [System.Core]System.Linq.Enumerable::First<string[0..., 0...]>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
	IL_0067: ret

Performance.

The last chance given to the Linq solution could be on the performance, so I tried to run both the conversions over a 100k loops each.
Here follow the results:

timings

Conclusion.

I would not use the Linq way ever, at least for such a cases. Frankly, I don’t see any benefit, other than a coding exercise.
Any of you does have a better solution?

Here is the source code of the application.

Hacking the WPF GridView – Final revised release

This is the third (and supposed last) article on how to hack the GridView (ListView) of the WPF.

To tell the truth, this post was yes planned, but just for explaining a subtle issue still present in the past release. However, after playing a while with that source, I noticed that another severe issue: a potential memory-leak when the column manager is not disposed together with the (Grid)view.
That caused a dramatic changing of the code, but luckily it comes in a simpler way that the previous one.

The subtle issue.

Let’s have a peek at the known issue, firstly.
It’s about the columns’ header, which allows the resizing of the width by dragging the buttons separator. That’s quite normal, but the issue came out when I tried to resize the latest visible column, whereas the next was hidden. In the following video the issue is very clear:

So, why that happens, and how to solve it?
I had a little effort on inspecting the problem, because the logical tree exposes the GridViewColumn instances, but the visual tree is rather different. Moreover, the embedded WPF visualizer in the Visual Studio (even the Ultimate version) is pretty limited and does not offer enough help in such a situation.
Finally, I decided to try the XAML Spy tool. It looks astonishingly, with a very modern yet attractive look, but that isn’t a trap.

Inspecting the application with XAML Spy.

IMHO, the best feature the XAML Spy tool has is the ability to inspect any running process; of course, it has to be any of the supported technologies, but with WPF, Silverlight, Windows Phone and Windows Store, I think you’ll cover anything but the web.
Once run, the spy asks for the target application to attach to. If the troubled app is already started, it’s pretty straightforward finding it among the “running processes”. In case you don’t see it at first glance, just refresh the Spy’s page.

xamlspy-1

Press “attach to process” when the target process has been selected.

Immediately, you’ll notice two things:

  • the XAML Spy app will turn to the inspection page, where many tools are available, and
  • a special blue tag will be shown in the top of the target window’s viewport.

xamlspy-2

It’s a drop-down menu (or whatever you want to call it), which offers a series of useful functions.

xamlspy-3

I must admit that I was shocked by seeing that I can enable a basic ruler: useful for sure for many pixel-perfect artworks, of any every-day app. Anyway, it is just a delightful feature of the XAML Spy, and not what we actually need for the inspection.

xamlspy-4

In the Visual Studio tree viewer, you have to scan the visual tree “by yourself”, in the sense that there’s no easing on a certain visual element. Sometime, on third-party components, you actually don’t have any idea on what to look for. Finally, when the tree is huge, the searching is more than a challenge.

Instead, the GUI inspection has been made easy with the XAML Spy. Just move the mouse over the desired (or suspected) point, and a dashed border will highlight the related visual element. Of course you can’t do everything, but it’s surely a dramatic quicker way to find the hot spot.

xamlspy-5

So, the goal is understanding why dragging the rightmost column header separator will reveal the hidden column. The visual inspection (see below) indicates that the sizing button is still available even the column has been hidden.

xamlspy-6

At this point, the simplest way to get around this behavior would be disabling the whole column (visual) fragment, but…will be a real solution.

One time more, the XAML Spy allows to change the value of a property directly by the aim of the left pane, which is a well-known property-grid. Let’s say that only a subset of the available properties can be modified at runtime with this feature. That’s because the WPF code, which turns to “frozen” many objects (especially whose created by a template-mechanism), thus no more modifiable externally.

xamlspy-7

So, turning the GridViewColumnHeader as NOT enabled (i.e. IsEnabled = False) is trivial, as well as verifying the result in no time.

xamlspy-8

The trick can be applied, so the only task to do now is implementing the mechanism in some way.
This is not complex at all, though. A simple converter will do the job: as soon the column width is larger than some pixel, it will disable automatically the whole column itself.

Here follows the converter’s code:

    /// <summary>
    /// This converter targets a column header,
    /// in order to disable it when its width
    /// is close to zero
    /// </summary>
    public class ColumnHeaderEnableConverter
        : IValueConverter
    {
        public object Convert(
            object value, 
            Type targetType, 
            object parameter, 
            System.Globalization.CultureInfo culture)
        {
            var width = (double)value;
            return width >= 3.0;
        }


        public object ConvertBack(
            object value, 
            Type targetType, 
            object parameter, 
            System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

    }

Then here is how to apply in the XAML:

               ...
        <ListView
            ItemsSource="{Binding Path=People, Source={x:Static local:App.Current}}"
            Grid.Row="1"
            x:Name="lvw1"
            >
            <ListView.Resources>
                <local:ColumnHeaderEnableConverter x:Key="cv1" />
                <Style TargetType="{x:Type GridViewColumnHeader}">
                    <Setter Property="IsEnabled" Value="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource cv1}}" />
                </Style>
            </ListView.Resources>

            <ListView.View>
               ...

The code rewriting.

As stated, the code presented on the past article has dramatically changed, due a potential memory-leak.
Let’s say that a real memory-leak won’t happen, just because the WPF underlying code checks for the proper GridViewColumn instantiation, and throws an exception. However, the issue is severe enough to take in account, and find a workaround.

The problem faces the inability to reuse the same GridViewColumn more than once, in any GridView context. Once you insert it in a view, either you remove or that can’t be used any more. Since detaching is a bit complex, the only reliable way to consider is to prevent any GridViewColumn reusing.
Better, the old columns’ manager (GridViewColumnsManager) is no more useful and it’s substituted by a very simple ObservableCollection of GridViewColumnWrapper. Then, most of the automation hosted in the old manager has been moved into the GridViewEx.
Honestly, it’s a much more elegant solution, and safer as well. Furthermore, it offers a more abstract column-wrapper source, with just a collection.
So, the GridViewEx code is the following:

    public class GridViewEx
        : GridView
    {
        
        #region DP ColumnsSource

        public static readonly DependencyProperty ColumnsSourceProperty = DependencyProperty.Register(
            "ColumnsSource",
            typeof(ObservableCollection<GridViewColumnWrapper>),
            typeof(GridViewEx),
            new PropertyMetadata(
                null,
                (obj, args) =>
                {
                    var ctl = (GridViewEx)obj;
                    ctl.ColumnsSourceChanged(args);
                }));


        public ObservableCollection<GridViewColumnWrapper> ColumnsSource
        {
            get { return (ObservableCollection<GridViewColumnWrapper>)GetValue(ColumnsSourceProperty); }
            set { SetValue(ColumnsSourceProperty, value); }
        }


        private void ColumnsSourceChanged(DependencyPropertyChangedEventArgs args)
        {
            ObservableCollection<GridViewColumnWrapper> source;

            source = args.OldValue as ObservableCollection<GridViewColumnWrapper>;
            if (source != null)
            {
                WeakEventManager<INotifyCollectionChanged, NotifyCollectionChangedEventArgs>.RemoveHandler(
                    source,
                    "CollectionChanged",
                    SourceItemsCollectionChanged
                    );
            }

            source = args.NewValue as ObservableCollection<GridViewColumnWrapper>;
            if (source != null)
            {
                WeakEventManager<INotifyCollectionChanged, NotifyCollectionChangedEventArgs>.AddHandler(
                    source,
                    "CollectionChanged",
                    SourceItemsCollectionChanged
                    );
            }

            this.Align();
        }

        #endregion


        void SourceItemsCollectionChanged(
            object sender,
            System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            this.Align();
        }


        /// <summary>
        /// Provides to align the target collection by the source's one.
        /// The default implementation is a simple positional one-to-one mirroring.
        /// </summary>
        /// <remarks>
        /// The wrapper and the actual column instances are compared by leveraging
        /// the column's hash code, which is stored privately inside the wrapper
        /// </remarks>
        protected virtual void Align()
        {
            if (this.ColumnsSource == null)
                return;

            int ixt = 0;
            for (int ixs = 0; ixs < this.ColumnsSource.Count; ixs++)
            {
                GridViewColumnWrapper wrapper = this.ColumnsSource[ixs];
                int pos = -1;

                if (this.Columns.Count > ixt)
                {
                    //search for the column equivalent to the current wrapper
                    pos = this.Columns.Count;
                    while (--pos >= 0 && this.Columns[pos].GetHashCode() != wrapper.ColumnHash) ;
                }

                if (pos >= 0)
                {
                    //the column was found, but adjust its position only
                    //when is not already correct
                    if (pos != ixt)
                        this.Columns.Move(pos, ixt);
                }
                else
                {
                    //the column was not found, so create a new one
                    var col = new GridViewColumn();
                    wrapper.ColumnHash = col.GetHashCode();

                    //simple copy of the header, so a further binding is also possible
                    col.Header = wrapper.Header;

                    //sets the initial (nominal) width of the column
                    col.Width = wrapper.Width;

                    //yields a column initialization, whereas available
                    if (wrapper.Initializer != null)
                    {
                        wrapper.Initializer(wrapper, col);
                    }

                    this.Columns.Insert(ixt, col);

                    //creates the behavior for the length animation
                    var bvr = new LengthAnimationBehavior(GridViewColumn.WidthProperty);
                    Interaction.GetBehaviors(col).Add(bvr);
                    bvr.ControlledValueChanged += bvr_ControlledValueChanged;

                    //binds the nominal width of the column to the behavior
                    BindingOperations.SetBinding(
                        bvr,
                        LengthAnimationBehavior.NominalLengthProperty,
                        new Binding("Width")
                        {
                            Source = wrapper,
                        });

                    //also binds the visibility to the behavior
                    BindingOperations.SetBinding(
                        bvr,
                        LengthAnimationBehavior.IsVisibleProperty,
                        new Binding("IsVisible")
                        {
                            Source = wrapper,
                        });

                    //now finally enables the animation
                    bvr.IsAnimationEnabled = true;
                }

                ixt++;
            }

            //removes any no further useful column
            while (this.Columns.Count > ixt)
                this.Columns.RemoveAt(ixt);
        }


        /// <summary>
        /// Event handler for the actual column's width changing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks>
        /// This is very useful for keeping track of the manual resizing
        /// of any grid-view column. Every width changing off the animation,
        /// will be notified here.
        /// </remarks>
        void bvr_ControlledValueChanged(object sender, ControlledValueChangedEventArgs e)
        {
            var col = (GridViewColumn)e.AssociatedObject;
            var hash = col.GetHashCode();
            var item = this.ColumnsSource.FirstOrDefault(_ => _.ColumnHash == hash);
            if (item != null)
            {
                //update the nominal width in the wrapper with
                //the desired one
                item.Width = col.Width;
            }
        }

    }

The above view is used as follows:

        <ListView
            ItemsSource="{Binding Path=People, Source={x:Static local:App.Current}}"
            Grid.Row="1"
            x:Name="lvw1"
            >
            <ListView.Resources>
                <local:ColumnHeaderEnableConverter x:Key="cv1" />
                <Style TargetType="{x:Type GridViewColumnHeader}">
                    <Setter Property="IsEnabled" Value="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource cv1}}" />
                </Style>
            </ListView.Resources>

            <ListView.View>
                <local:GridViewEx
                    AllowsColumnReorder="False"
                    ColumnsSource="{Binding Path=.}"
                    >
                </local:GridViewEx>
            </ListView.View>
        </ListView>

That’s much simplified than the past solution, because even the underlying code has got simpler:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }


        private readonly ObservableCollection<GridViewColumnWrapper> _manager = new ObservableCollection<GridViewColumnWrapper>();


        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (this._manager.Count == 0)
            {
                //the very first time, the manager should be
                //filled up with the desired columns
                this.AddItem("FirstName", 100, true);
                this.AddItem("LastName", 100, true);
                //this.AddItem("Company", 150, true);

                this.AddItem("Address", 200, false);
                this.AddItem("City", 120, false);
                //this.AddItem("County", 100, false);
                this.AddItem("State", 50, false);
                this.AddItem("ZIP", 60, false);

                this.AddItem("Phone", 150, false);
                //this.AddItem("Fax", 100, false);
                this.AddItem("Email", 150, false);
                //this.AddItem("Web", 180, false);
            }

            //create then show the secondary window,
            //containing the grid
            var win = new Window1();
            win.Owner = this;
            win.DataContext = this._manager;
            win.ShowDialog();
        }


        //just a helper for creating a column wrapper
        private void AddItem(string caption, double width, bool isVisible)
        {
            var mi = new GridViewColumnWrapper();
            mi.Header = caption;
            mi.Width = width;
            mi.IsVisible = isVisible;

            //here is the opportunity to set the cell content:
            //either a direct data or even a more useful data-binding
            mi.Initializer = (sender, gvc) => gvc.DisplayMemberBinding = new Binding(caption);

            this._manager.Add(mi);
        }

    }

Conclusion.

Hopefully this release will be the final one. I test this source better in the near future, and any improvement or bug will be fixed accordingly.
Really can’t miss a final word on the XAML Spy tool, which surprised me a lot for the amazing features it offers. However, as seen, the flexibility of such a tool dramatically cuts the time of debugging and inspecting apps, especially when they’re running.

Here is the source code of the app.

Hacking the WPF GridView – Adding the animation

UPDATE: this article still deserves a bit of mention, but has been superseded by a revision of the code due to some issues. Please, have a look at this article instead.

In the first part of the WPF GridView hacking, I shown how to hide one or more column upon a certain boolean source.
Here I’ll show you a little complex hacking in order to achieve the same functionality, but adding an animation to get the collapsing/expanding ability more fancy.
Just to let you understand better what’s the goal, have a look at this short video:

How to approach the problem?

The animation capability is a well built-in feature of the WPF. I first considered to leverage the animation by using a StoryBoard or a simpler BeginAnimation over the GridViewColumn’s Width property, but…
The simplest way to animate a property is using the BeginAnimation, without any StoryBoard. However, this works only in code, and you must use a StoryBoard when in the XAML.
The following example is taken from the MSDN library documentation:

// Animate the button's width.
DoubleAnimation widthAnimation = new DoubleAnimation(120, 300, TimeSpan.FromSeconds(5));
widthAnimation.RepeatBehavior = RepeatBehavior.Forever;
widthAnimation.AutoReverse = true;
animatedButton.BeginAnimation(Button.WidthProperty, widthAnimation);

The above snippet indicates that a simple converter won’t help us for the animation, but we actually need some powerful tool.

Derive from a Behavior generic class.

It’s a been that the WPF added the powerful capability of adding one or more Behaviors to any DependencyObject-derived object. A Behavior is an elegant way to extend the functionality of a certain object, whereas it is not possible to directly modify it. I’d also add that even having the ability to modify it, a behavioral-pattern yields a lot of abstraction, thus a much greater component reuse.
At this point, the behavior should have to be attached to the GridViewColumn instance, and should also expose at least two properties:

  • IsVisible, of type Boolean, which aims the control of the related column’s visibility, and
  • NominalWidth, of type Double, which specifies the expanded-state width of the same column.

Once attached, the behavior should control the Width property of the owning’s column. Something like this:

    public class WidthAnimationBehavior
        : Behavior<GridViewColumn>
    {

        #region DP NominalLength

        public static readonly DependencyProperty NominalLengthProperty = DependencyProperty.Register(
            "NominalLength",
            typeof(double),
            typeof(WidthAnimationBehavior),
            new PropertyMetadata(
                double.NaN,
                (obj, args) =>
                {
                    var ctl = (WidthAnimationBehavior)obj;
                    ctl.NominalLengthChanged(args);
                }));


        /// <summary>
        /// Represent the nominal length value to be considered
        /// when the element is visible
        /// </summary>
        public double NominalLength
        {
            get { return (double)GetValue(NominalLengthProperty); }
            set { SetValue(NominalLengthProperty, value); }
        }


        private void NominalLengthChanged(DependencyPropertyChangedEventArgs args)
        {
            this.TriggerAnimation();
        }

        #endregion


        #region DP IsVisible

        public static readonly DependencyProperty IsVisibleProperty = DependencyProperty.Register(
            "IsVisible",
            typeof(bool),
            typeof(WidthAnimationBehavior),
            new PropertyMetadata(
                false,
                (obj, args) =>
                {
                    var ctl = (WidthAnimationBehavior)obj;
                    ctl.IsVisibleChanged(args);
                }));


        /// <summary>
        /// Get and set whether the element has to be considered visible.
        /// In this context, the "visibility" is meant as the element's
        /// length expanded (nominal length) or collapsed (zero).
        /// </summary>
        public bool IsVisible
        {
            get { return (bool)GetValue(IsVisibleProperty); }
            set { SetValue(IsVisibleProperty, value); }
        }


        private void IsVisibleChanged(DependencyPropertyChangedEventArgs args)
        {
            this.TriggerAnimation();
        }

        #endregion


        private void TriggerAnimation()
        {
            var targetWidth = this.IsVisible
                ? this.NominalLength
                : 0.0;

            if (targetWidth > 0.0 &&
                this.AssociatedObject.Width == 0.0)
            {
                //begin open

            }
            else if (targetWidth == 0.0 &&
                this.AssociatedObject.Width > 0.0)
            {
                //begin close
                
            }
        }
    }

The actual problem is that the BeginAnimation method is declared in the Animatable class, but the GridViewColumn class does not derive from it.
Let’s continue digging…

Use a timer instead…

Of course there are many ways to manage an animation: I believe the most straightforward is using a normal timer as a clock. Better, a DispatcherTimer, since the goal is dealing heavily with the UI thread, and a specific timer will surely lead a better result.
The above behavior class gets a bit more complex, but still offers a decent functionality without messing the code too much.
Here is the revised class:

    public class WidthAnimationBehavior
        : Behavior<GridViewColumn>
    {
        /// <summary>
        /// Define how long takes the animation
        /// </summary>
        /// <remarks>
        /// The value is expressed as clock interval units
        /// </remarks>
        private const int StepCount = 10;


        public WidthAnimationBehavior()
        {
            //create the clock used for the animation
            this._clock = new DispatcherTimer(DispatcherPriority.Render);
            this._clock.Interval = TimeSpan.FromMilliseconds(20);
            this._clock.Tick += _clock_Tick;
        }


        private DispatcherTimer _clock;
        private int _animationStep;
        private double _fromLength;
        private double _toLength;


        #region DP NominalLength

        public static readonly DependencyProperty NominalLengthProperty = DependencyProperty.Register(
            "NominalLength",
            typeof(double),
            typeof(WidthAnimationBehavior),
            new PropertyMetadata(
                double.NaN,
                (obj, args) =>
                {
                    var ctl = (WidthAnimationBehavior)obj;
                    ctl.NominalLengthChanged(args);
                }));


        /// <summary>
        /// Represent the nominal length value to be considered
        /// when the element is visible
        /// </summary>
        public double NominalLength
        {
            get { return (double)GetValue(NominalLengthProperty); }
            set { SetValue(NominalLengthProperty, value); }
        }


        private void NominalLengthChanged(DependencyPropertyChangedEventArgs args)
        {
            this.TriggerAnimation();
        }

        #endregion


        #region DP IsVisible

        public static readonly DependencyProperty IsVisibleProperty = DependencyProperty.Register(
            "IsVisible",
            typeof(bool),
            typeof(WidthAnimationBehavior),
            new PropertyMetadata(
                false,
                (obj, args) =>
                {
                    var ctl = (WidthAnimationBehavior)obj;
                    ctl.IsVisibleChanged(args);
                }));


        /// <summary>
        /// Get and set whether the element has to be considered visible.
        /// In this context, the "visibility" is meant as the element's
        /// length expanded (nominal length) or collapsed (zero).
        /// </summary>
        public bool IsVisible
        {
            get { return (bool)GetValue(IsVisibleProperty); }
            set { SetValue(IsVisibleProperty, value); }
        }


        private void IsVisibleChanged(DependencyPropertyChangedEventArgs args)
        {
            this.TriggerAnimation();
        }

        #endregion


        private void TriggerAnimation()
        {
            this._animationStep = StepCount;
            this._clock.IsEnabled = true;
        }


        /// <summary>
        /// Clock ticker, mainly used for the animation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _clock_Tick(object sender, EventArgs e)
        {
            if (this.AssociatedObject != null)
            {
                if (this._animationStep-- == StepCount)
                {
                    //calculates the from/to values to be used for the animation
                    this._fromLength = double.IsNaN(this.AssociatedObject.Width) ? 0.0 : this.AssociatedObject.Width;
                    this._toLength = this.NominalLength * (this.IsVisible ? 1.0 : 0.0);

                    if (Math.Abs(this._toLength - this._fromLength) < 0.1)
                    {
                        //the points match, thus there's no needs to animate
                        this._animationStep = 0;
                        this._clock.Stop();
                    }
                }

                if (this._clock.IsEnabled)
                {
                    //applies the easing function, whereas defined
                    double relative = (StepCount - this._animationStep) / (double)StepCount;
                    double value = this._fromLength + relative * (this._toLength - this._fromLength);

                    this.AssociatedObject.Width = value;
                }

                if (this._animationStep <= 0)
                {
                    //the animation is over: stop the clock
                    this._animationStep = 0;
                    this._clock.Stop();
                }
            }
            else
            {
                //no animation or no target: stop the clock immediately
                this._animationStep = 0;
                this._clock.Stop();
            }
        }

    }

On the XAML side, the documenti will show as follows:

<ListView
    ItemsSource="{Binding Path=People, Source={x:Static local:App.Current}}"
    Grid.Row="1"
    x:Name="lvw1"
    >
    <ListView.View>
        <GridView
            AllowsColumnReorder="False"
            >
            <GridViewColumn Header="FirstName" Width="100" DisplayMemberBinding="{Binding Path=FirstName}" />
            <GridViewColumn Header="LastName" Width="100" DisplayMemberBinding="{Binding Path=LastName}" />

            <GridViewColumn Header="Address" DisplayMemberBinding="{Binding Path=Address}">
                <i:Interaction.Behaviors>
                    <local:WidthAnimationBehavior NominalLength="200" IsVisible="{Binding Path=IsChecked, ElementName=ChkLoc}" />
                </i:Interaction.Behaviors>
            </GridViewColumn>

            <GridViewColumn Header="City" Width="120" DisplayMemberBinding="{Binding Path=City}" />
            <GridViewColumn Header="State" Width="50" DisplayMemberBinding="{Binding Path=State}" />
            <GridViewColumn Header="ZIP" Width="60" DisplayMemberBinding="{Binding Path=ZIP}" />
                    
            <GridViewColumn Header="Phone" Width="150" DisplayMemberBinding="{Binding Path=Phone}" />
            <GridViewColumn Header="Email" Width="150" DisplayMemberBinding="{Binding Path=Email}" />
        </GridView>
    </ListView.View>
</ListView>

NOTE: for readiness reasons, the XAML snippet shown is just the ListView. Also, the behavior has been applied only to the “Address” column, but it could have be applied to any other column.

Again, there’s no code behind, and that’s a good news. The usage in the XAML context is not much complex than using a normal converter. Most of the uncommon tag structure is due by the attached collection, which holds the real behavior instance.
How is the result now? This video says more than thousand words!

So, everything seems fine!…Well, not at all yet.
When the column is expanded (i.e. visible) I should be able to resize, whereas this is a desired feature. By the way, I can do it, but the new width is not stored anywhere, and a new collapse/expansion will lose the desired setting.

A dramatic new approach.

Okay, I need also another feature: the ability to add/remove the columns at runtime. That’s because our LOB app for the timber drying regulation (Cet Electronics), can’t rely on a prefixed set of columns, and the real set depends on the regulator model/state.
Moreover, the animation behavior runs fine, but…why not rethink that class in order to use for many more double-value animations?
That’s for saying that the above trick is valuable for many applications, yet not enough for a pretty flexible usage in a professional context.
So, I approached the GridViewColumns management via a proxy, where each column is mirrored by a view-model instance. I don’t know if the term “view-model” is appropriate in this case, because the GridViewColumn is actually a kind of view-model for the real elements hosted in the visual tree.
Anyway, the deal is hosting this “proxy” in some place, where the business layer would adjust the virtual columns as it wants. At that point the view (i.e. a ListView+GridView) may bind safely to this proxy, thus the visual result should match the expectations.

As for “safely”, I mean without any kind of memory-leak.

For the final solution the XAML is amazingly clean, but it’s also obvious because most of the work is done in the code behind.

<Window 
    x:Class="ListViewHacking.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ListViewHacking"
    Title="ListView hacking demo" 
    Height="480" Width="900"
    WindowStartupLocation="CenterOwner"
    FontSize="14"
    Background="{StaticResource BG}"
    >
    
        
    <Grid
        Margin="50,40"
        >
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        
        <StackPanel
            Orientation="Horizontal"
            Grid.Row="0"
            Margin="20,8"
            >
            <CheckBox Content="Show location columns" x:Name="ChkLoc" Click="ChkLoc_Click" Margin="20,0" />
            <CheckBox Content="Show contact columns" x:Name="ChkCont" Click="ChkCont_Click" Margin="20,0" />
        </StackPanel>
        
        <ListView
            ItemsSource="{Binding Path=People, Source={x:Static local:App.Current}}"
            Grid.Row="1"
            x:Name="lvw1"
            >
            <ListView.View>
                <local:GridViewEx
                    AllowsColumnReorder="False"
                    ColumnsSource="{Binding Path=TargetCollection}"
                    >
                </local:GridViewEx>
            </ListView.View>
        </ListView>
        
    </Grid>
</Window>

However, there’s a minimal handling for the checkboxes’ events:

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }


        private void ChkLoc_Click(object sender, RoutedEventArgs e)
        {
            var mirror = (GridViewColumnManager)this.DataContext;
            var isVisible = this.ChkLoc.IsChecked == true;

            //manage the visibility for the specified columns
            for (int i = 2; i <= 5; i++)
            {
                mirror.SourceItems[i].IsVisible = isVisible;
            }
        }


        private void ChkCont_Click(object sender, RoutedEventArgs e)
        {
            var mirror = (GridViewColumnManager)this.DataContext;
            var isVisible = this.ChkCont.IsChecked == true;

            //manage the visibility for the specified columns
            for (int i = 6; i <= 7; i++)
            {
                mirror.SourceItems[i].IsVisible = isVisible;
            }
        }

    }

Now, the columns’ configuration is fully done in the code behind, specifically in the main window:

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }


        private GridViewColumnManager _manager = new GridViewColumnManager();


        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (this._manager.SourceItems.Count == 0)
            {
                //the very first time, the manager should be
                //filled up with the desired columns
                this.AddItem("FirstName", 100, true);
                this.AddItem("LastName", 100, true);

                this.AddItem("Address", 200, false);
                this.AddItem("City", 120, false);
                this.AddItem("State", 50, false);
                this.AddItem("ZIP", 60, false);

                this.AddItem("Phone", 150, false);
                this.AddItem("Email", 150, false);
            }

            //create then show the secondary window,
            //containing the grid
            var win = new Window1();
            win.Owner = this;
            win.DataContext = this._manager;
            win.ShowDialog();
        }


        //just a helper for creating a column wrapper
        private void AddItem(string caption, double width, bool isVisible)
        {
            var mi = new GridViewColumnWrapper();
            mi.Header = caption;
            mi.Width = width;
            mi.IsVisible = isVisible;

            //here is the opportunity to set the cell content:
            //either a direct data or even a more useful data-binding
            mi.Initializer = (sender, gvc) => gvc.DisplayMemberBinding = new Binding(caption);
            
            this._manager.SourceItems.Add(mi);
        }

    }

Here is the final version of the behavior:

    /// <summary>
    /// Perform a length animation overtime, without using data binding.
    /// It is a normal behavior that can be attached to any <see cref="System.Windows.DependencyObject"/>
    /// </summary>
    /// <remarks>
    /// Currently only the <see cref="System.Double"/> type is supported
    /// </remarks>
    public class LengthAnimationBehavior
        : Behavior<DependencyObject>
    {
        /// <summary>
        /// Define how long is the delay time before actually starting the animation
        /// </summary>
        /// <remarks>
        /// The value is expressed as clock interval units
        /// </remarks>
        private const int DelayCount = 10;

        /// <summary>
        /// Define how long takes the animation
        /// </summary>
        /// <remarks>
        /// The value is expressed as clock interval units
        /// </remarks>
        private const int StepCount = 10;


        /// <summary>
        /// Create the instance and specify what's
        /// the target property to animate
        /// </summary>
        /// <param name="dp"></param>
        public LengthAnimationBehavior(DependencyProperty dp)
        {
            this._dp = dp;

            //create the clock used for the animation
            this._clock = new DispatcherTimer(DispatcherPriority.Render);
            this._clock.Interval = TimeSpan.FromMilliseconds(20);
            this._clock.Tick += _clock_Tick;

            //see: http://wpf-animation.googlecode.com/svn/trunk/src/WPF/Animation/PennerDoubleAnimation.cs
            this.EasingFunction = (t, b, c, d) =>
            {
                //a quintic easing function
                if ((t /= d / 2) < 1)
                    return c / 2 * t * t * t * t * t + b;
                else
                    return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
            };
        }


        private DependencyProperty _dp;

        private DispatcherTimer _clock;
        private int _animationStep;
        private double _fromLength;
        private double _toLength;

        /// <summary>
        /// Get and set the easing function to be used for the animation
        /// </summary>
        public Func<double, double, double, double, double> EasingFunction { get; set; }


        #region DP NominalLength

        public static readonly DependencyProperty NominalLengthProperty = DependencyProperty.Register(
            "NominalLength",
            typeof(double),
            typeof(LengthAnimationBehavior),
            new PropertyMetadata(
                double.NaN,
                (obj, args) =>
                {
                    var ctl = (LengthAnimationBehavior)obj;
                    ctl.NominalLengthChanged(args);
                }));


        /// <summary>
        /// Represent the nominal length value to be considered
        /// when the element is visible
        /// </summary>
        public double NominalLength
        {
            get { return (double)GetValue(NominalLengthProperty); }
            set { SetValue(NominalLengthProperty, value); }
        }


        private void NominalLengthChanged(DependencyPropertyChangedEventArgs args)
        {
            if (this.IsAnimationEnabled)
            {
                this._animationStep = DelayCount + StepCount;
                this._clock.IsEnabled = true;
            }
            else
            {
                this.SetImmediately();
            }
        }

        #endregion


        #region DP TargetValue

        private static readonly DependencyProperty TargetValueProperty = DependencyProperty.Register(
            "TargetValue",
            typeof(object),
            typeof(LengthAnimationBehavior),
            new PropertyMetadata(
                null,
                (obj, args) =>
                {
                    var ctl = (LengthAnimationBehavior)obj;
                    ctl.TargetValueChanged(args);
                }));


        /// <summary>
        /// Used as mirror of the target property value.
        /// It's a simple way to be notified of any value change
        /// </summary>
        /// <remarks>
        /// Please, note that's everything private
        /// </remarks>
        private object TargetValue
        {
            get { return (object)GetValue(TargetValueProperty); }
            set { SetValue(TargetValueProperty, value); }
        }


        private void TargetValueChanged(DependencyPropertyChangedEventArgs args)
        {
            if (this.IsVisible &&
                (this._animationStep <= 0 || this._animationStep > StepCount))
            {
                //fire the related event
                this.OnControlledValueChanged(this.AssociatedObject);
            }
        }

        #endregion


        #region DP IsVisible

        public static readonly DependencyProperty IsVisibleProperty = DependencyProperty.Register(
            "IsVisible",
            typeof(bool),
            typeof(LengthAnimationBehavior),
            new PropertyMetadata(
                false,
                (obj, args) =>
                {
                    var ctl = (LengthAnimationBehavior)obj;
                    ctl.IsVisibleChanged(args);
                }));


        /// <summary>
        /// Get and set whether the element has to be considered visible.
        /// In this context, the "visibility" is meant as the element's
        /// length expanded (nominal length) or collapsed (zero).
        /// </summary>
        public bool IsVisible
        {
            get { return (bool)GetValue(IsVisibleProperty); }
            set { SetValue(IsVisibleProperty, value); }
        }


        private void IsVisibleChanged(DependencyPropertyChangedEventArgs args)
        {
            if (this.IsAnimationEnabled)
            {
                this._animationStep = DelayCount + StepCount;
                this._clock.IsEnabled = true;
            }
            else
            {
                this.SetImmediately();
            }
        }

        #endregion


        #region DP IsAnimationEnabled

        public static readonly DependencyProperty IsAnimationEnabledProperty = DependencyProperty.Register(
            "IsAnimationEnabled",
            typeof(bool),
            typeof(LengthAnimationBehavior),
            new PropertyMetadata(
                false,
                (obj, args) =>
                {
                    var ctl = (LengthAnimationBehavior)obj;
                    ctl.IsAnimationEnabledChanged(args);
                }));


        /// <summary>
        /// Get or set whether the animation should run or not.
        /// When disabled, any setting will take place immediately
        /// </summary>
        public bool IsAnimationEnabled
        {
            get { return (bool)GetValue(IsAnimationEnabledProperty); }
            set { SetValue(IsAnimationEnabledProperty, value); }
        }


        private void IsAnimationEnabledChanged(DependencyPropertyChangedEventArgs args)
        {
            if ((bool)args.NewValue == false)
            {
                this._animationStep = 0;
                this._clock.Stop();
            }
        }

        #endregion


        /// <summary>
        /// Allow to set the new target length immediately,
        /// without any animation or delay
        /// </summary>
        private void SetImmediately()
        {
            if (this.AssociatedObject != null)
            {
                this.AssociatedObject.SetValue(
                    this._dp,
                    this.NominalLength * (this.IsVisible ? 1.0 : 0.0)
                    );
            }
        }


        /// <summary>
        /// Clock ticker, mainly used for the animation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _clock_Tick(object sender, EventArgs e)
        {
            if (this.IsAnimationEnabled &&
                this.AssociatedObject != null)
            {
                //check the initial delay
                if (--this._animationStep > StepCount)
                    return;

                //when the delay expires...
                if (this._animationStep == StepCount)
                {
                    //...calculates the from/to values to be used for the animation
                    this._fromLength = (double)this.TargetValue;
                    this._toLength = this.NominalLength * (this.IsVisible ? 1.0 : 0.0);

                    if (Math.Abs(this._toLength - this._fromLength) < 0.1)
                    {
                        //the points match, thus there's no needs to animate
                        this._animationStep = 0;
                        this._clock.Stop();
                    }
                }

                if (this._clock.IsEnabled)
                {
                    //applies the easing function, whereas defined
                    double value = this.EasingFunction(
                        StepCount - this._animationStep,
                        this._fromLength,
                        this._toLength - this._fromLength,
                        StepCount
                        );

                    this.AssociatedObject.SetValue(
                        this._dp,
                        value
                        );
                }

                if (this._animationStep <= 0)
                {
                    //the animation is over: stop the clock
                    this._animationStep = 0;
                    this._clock.Stop();
                }
            }
            else
            {
                //no animation or no target: stop the clock immediately
                this._animationStep = 0;
                this._clock.Stop();
            }
        }


        /// <summary>
        /// The behavior has just been attached to the object
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();

            BindingOperations.SetBinding(
                this,
                LengthAnimationBehavior.TargetValueProperty,
                new Binding()
                {
                    Path = new PropertyPath(this._dp),
                    Source = this.AssociatedObject,
                    Mode = BindingMode.OneWay,
                });
        }


        /// <summary>
        /// The behavior has just been detached to the object
        /// </summary>
        protected override void OnDetaching()
        {
            BindingOperations.ClearBinding(
                this,
                LengthAnimationBehavior.TargetValueProperty
                );

            base.OnDetaching();
        }


        #region EVT ControlledValueChanged

        /// <summary>
        /// Provide the notification of any change
        /// of the target property value, when the animation
        /// is not active
        /// </summary>
        public event EventHandler<ControlledValueChangedEventArgs> ControlledValueChanged;


        private void OnControlledValueChanged(DependencyObject associated)
        {
            var handler = this.ControlledValueChanged;

            if (handler != null)
            {
                handler(
                    this,
                    new ControlledValueChangedEventArgs(associated)
                    );
            }
        }

        #endregion

    }


    /// <summary>
    /// Event arguments for the notification of any change
    /// of the target property value, when the animation
    /// is not active
    /// </summary>
    public class ControlledValueChangedEventArgs
        : EventArgs
    {
        public ControlledValueChangedEventArgs(DependencyObject associated)
        {
            this.AssociatedObject = associated;
        }

        public DependencyObject AssociatedObject { get; private set; }
    }

Here is the proxy manager and a minimal realization of the column mirror model:

    /// <summary>
    /// Proxy for the columns collection used in a grid-view
    /// </summary>
    public class GridViewColumnManager
    {
        public GridViewColumnManager()
        {
            //create the source items collection instance
            this._sourceItems = new ObservableCollection<GridViewColumnWrapper>();
            this._sourceItems.CollectionChanged += SourceItemsCollectionChanged;

            //create the target columns collection instance
            this._targetCollection = new ObservableCollection<GridViewColumn>();
        }


        #region PROP SourceItems

        private readonly ObservableCollection<GridViewColumnWrapper> _sourceItems;

        /// <summary>
        /// Collection reference for the column wrapper items
        /// </summary>
        public ObservableCollection<GridViewColumnWrapper> SourceItems 
        {
            get { return this._sourceItems; }
        }

        #endregion


        #region PROP TargetCollection

        private readonly ObservableCollection<GridViewColumn> _targetCollection;

        /// <summary>
        /// Columns collection reference for the grid-view
        /// </summary>
        public IEnumerable<GridViewColumn> TargetCollection
        {
            get { return this._targetCollection; }
        }

        #endregion


        void SourceItemsCollectionChanged(
            object sender,
            System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            this.Align();
        }


        /// <summary>
        /// Provides to align the target collection by the source's one.
        /// The default implementation is a simple positional one-to-one mirroring.
        /// </summary>
        /// <remarks>
        /// The wrapper and the actual column instances are compared by leveraging
        /// the column's hash code, which is stored privately inside the wrapper
        /// </remarks>
        protected virtual void Align()
        {
            int ixt = 0;
            for (int ixs = 0; ixs < this._sourceItems.Count; ixs++)
            {
                GridViewColumnWrapper wrapper = this._sourceItems[ixs];
                int pos = -1;

                if (this._targetCollection.Count > ixt)
                {
                    //search for the column equivalent to the current wrapper
                    pos = this._targetCollection.Count;
                    while (--pos >= 0 && this._targetCollection[pos].GetHashCode() != wrapper.ColumnHash) ;
                }

                if (pos >= 0)
                {
                    //the column was found, but adjust its position only
                    //when is not already correct
                    if (pos != ixt)
                        this._targetCollection.Move(pos, ixt);
                }
                else
                {
                    //the column was not found, so create a new one
                    var col = new GridViewColumn();
                    wrapper.ColumnHash = col.GetHashCode();

                    //simple copy of the header, so a further binding is also possible
                    col.Header = wrapper.Header;

                    //sets the initial (nominal) width of the column
                    col.Width = wrapper.Width;

                    //yields a column initialization, whereas available
                    if (wrapper.Initializer != null)
                    {
                        wrapper.Initializer(wrapper, col);
                    }

                    this._targetCollection.Insert(ixt, col);

                    //creates the behavior for the length animation
                    var bvr = new LengthAnimationBehavior(GridViewColumn.WidthProperty);
                    Interaction.GetBehaviors(col).Add(bvr);
                    bvr.ControlledValueChanged += bvr_ControlledValueChanged;

                    //binds the nominal width of the column to the behavior
                    BindingOperations.SetBinding(
                        bvr,
                        LengthAnimationBehavior.NominalLengthProperty,
                        new Binding("Width")
                        {
                            Source = wrapper,
                        });

                    //also binds the visibility to the behavior
                    BindingOperations.SetBinding(
                        bvr,
                        LengthAnimationBehavior.IsVisibleProperty,
                        new Binding("IsVisible")
                        {
                            Source = wrapper,
                        });

                    //now finally enables the animation
                    bvr.IsAnimationEnabled = true;
                }

                ixt++;
            }

            //removes any no further useful column
            while (this._targetCollection.Count > ixt)
                this._targetCollection.RemoveAt(ixt);
        }


        /// <summary>
        /// Event handler for the actual column's width changing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks>
        /// This is very useful for keeping track of the manual resizing
        /// of any grid-view column. Every width changing off the animation,
        /// will be notified here.
        /// </remarks>
        void bvr_ControlledValueChanged(object sender, ControlledValueChangedEventArgs e)
        {
            var col = (GridViewColumn)e.AssociatedObject;
            var hash = col.GetHashCode();
            var item = this._sourceItems.FirstOrDefault(_ => _.ColumnHash == hash);
            if (item != null)
            {
                //update the nominal width in the wrapper with
                //the desired one
                item.Width = col.Width;
            }
        }

    }


    public class GridViewColumnWrapper
        : INotifyPropertyChanged
    {

        internal int ColumnHash;

        public string Name { get; set; }
        public Action<GridViewColumnWrapper, GridViewColumn> Initializer { get; set; }


        #region PROP Header

        private object _header;

        public object Header
        {
            get { return this._header; }
            set
            {
                if (this._header != value)
                {
                    this._header = value;
                    this.OnPropertyChanged("Header");
                }
            }
        }

        #endregion


        #region PROP Width

        private double _width;

        public double Width
        {
            get { return this._width; }
            set
            {
                if (this._width != value)
                {
                    this._width = value;
                    this.OnPropertyChanged("Width");
                }
            }
        }

        #endregion


        #region PROP IsVisible

        private bool _isVisible;

        public bool IsVisible
        {
            get { return this._isVisible; }
            set
            {
                if (this._isVisible != value)
                {
                    this._isVisible = value;
                    this.OnPropertyChanged("IsVisible");
                }
            }
        }

        #endregion


        #region EVT PropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;


        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = this.PropertyChanged;

            if (handler != null)
            {
                handler(
                    this,
                    new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

    }

Finally, a derivation of the native GridView, because we need the ability to bind its column collection, but it is not available.

    public class GridViewEx
        : GridView
    {

        #region DP ColumnsSource

        public static readonly DependencyProperty ColumnsSourceProperty = DependencyProperty.Register(
            "ColumnsSource",
            typeof(ObservableCollection<GridViewColumn>),
            typeof(GridViewEx),
            new PropertyMetadata(
                null,
                (obj, args) =>
                {
                    var ctl = (GridViewEx)obj;
                    ctl.ColumnsSourceChanged(args);
                }));


        public ObservableCollection<GridViewColumn> ColumnsSource
        {
            get { return (ObservableCollection<GridViewColumn>)GetValue(ColumnsSourceProperty); }
            set { SetValue(ColumnsSourceProperty, value); }
        }


        private void ColumnsSourceChanged(DependencyPropertyChangedEventArgs args)
        {
            ObservableCollection<GridViewColumn> source;

            source = args.OldValue as ObservableCollection<GridViewColumn>;
            if (source != null)
            {
                source.CollectionChanged -= source_CollectionChanged;
            }

            this.Columns.Clear();

            source = args.NewValue as ObservableCollection<GridViewColumn>;
            if (source != null)
            {
                foreach (var col in source)
                {
                    this.Columns.Add(col);
                }

                source.CollectionChanged += source_CollectionChanged;
            }
        }

        #endregion


        void source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    this.Columns.Add((GridViewColumn)e.NewItems[0]);
                    break;

                case NotifyCollectionChangedAction.Remove:
                    this.Columns.Remove((GridViewColumn)e.OldItems[0]);
                    break;

                case NotifyCollectionChangedAction.Move:
                    this.Columns.Move(e.OldStartingIndex, e.NewStartingIndex);
                    break;

                case NotifyCollectionChangedAction.Replace:
                    this.Columns[e.NewStartingIndex] = (GridViewColumn)e.NewItems[0];
                    break;

                case NotifyCollectionChangedAction.Reset:
                    this.Columns.Clear();
                    break;
            }
        }

    }

If you noticed, in the demo video the grid is hosted in a separate window than the main one. That’s for two reasons:

  • verify that the closure of the child windows won’t lead to any leak, and
  • verify that any manual width change on the columns has to be preserved even when the window is destroyed.

Conclusion.

I know, the final version is pretty complex when compared to the solution seen till now. However, the benefits are noticeable: here are briefly summarized:

  • Of course, the primary target is fully available: each column can be hidden or shown, via a simple bool setting;
  • the columns’ configuration is totally controlled by the back view-model;
  • ease of save/load (persist) the user’s size setting;
  • the animation behavior is now a more generic “animation of a length” (of type Double);
  • there was an effort to avoid any modification of the style of the ListView, so that all the functionality should not have any impact with the user’s style;

Next time, we’ll see that even this final release is not perfect, and it has a subtle issue. We’ll learn how to fix it by leveraging the right tool!

By clicking here, you may download the basic (simplified) demo application. Click here to download the final release, instead.

Hacking the WPF GridView – How to hide columns

First part of (supposed) three about some tricky hackings around the WPF GridView, most used view mode of the very versatile ListView.
I think the ListView + GridView is a very good compromise for many grid-layered collection-presentation: simple but never uselessly complex.

In this first section I’ll show how to solve a pretty common task: control the visibility of a column.
That should be trivial if only the GridView (that is the GridViewColumn class) would have exposed any visibility property. So, it appears that the simplest way is to control the column’s width: by taking it to zero, the column actually disappear.
Note that this trick won’t prevent the columns to be part of the visual tree: it is still there, although the size is irrelevant.

Create the base application.

First off, we should create a base application to work with. That app should provide a bunch of data (the classic “Person” class), then present them in a grid-viewed fashion.
I got the data from a useful web site. The site offers several various-sized data set for a typical usage. I chose the set with 500 records. I never had to deal with huge set of data, instead with complex shaped. However, that’s not the focus.
Again, in the attached app there is the code to parse the CSV dataset: it’s simple, but this post won’t focus on how to parse it.

So, here follows the XAML source to show the data set on a GridView shaped ListView.

<Window 
    x:Class="ListViewHacking.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ListViewHacking"
    Title="ListView hacking demo" 
    Height="480" Width="900"
    WindowStartupLocation="CenterScreen"
    FontSize="14"
    Background="{StaticResource BG}"
    >
    
    <Grid
        Margin="50,40"
        >
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <StackPanel
            Orientation="Horizontal"
            Grid.Row="0"
            Margin="20,8"
            >
            <CheckBox Content="Show location columns" x:Name="ChkLoc" Margin="20,0" />
            <CheckBox Content="Show contact columns" x:Name="ChkCont" Margin="20,0" />
        </StackPanel>

        <ListView
            ItemsSource="{Binding Path=People, Source={x:Static local:App.Current}}"
            Grid.Row="1"
            >
            <ListView.Resources>
                <local:ColumnWidthConverter x:Key="cvColumnWidth" />
            </ListView.Resources>
            
            <ListView.View>
                <GridView
                    AllowsColumnReorder="False"
                    >
                    <GridViewColumn Header="FirstName" Width="100" DisplayMemberBinding="{Binding Path=FirstName}" />
                    <GridViewColumn Header="LastName" Width="100" DisplayMemberBinding="{Binding Path=LastName}" />

                    <GridViewColumn Header="Address" Width="200" DisplayMemberBinding="{Binding Path=Address}" />
                    <GridViewColumn Header="City" Width="120" DisplayMemberBinding="{Binding Path=City}" />
                    <GridViewColumn Header="State" Width="50" DisplayMemberBinding="{Binding Path=State}" />
                    <GridViewColumn Header="ZIP" Width="60" DisplayMemberBinding="{Binding Path=ZIP}" />
                    
                    <GridViewColumn Header="Phone" Width="150" DisplayMemberBinding="{Binding Path=Phone}" />
                    <GridViewColumn Header="Email" Width="150" DisplayMemberBinding="{Binding Path=Email}" />
                </GridView>
            </ListView.View>
        </ListView>

    </Grid>
</Window>

Note that there’s no underlying C# code behind this XAML.
The result, once started, is the following:

listview1

A converter for the column width.

As stated, the simplest way to control the column width by a boolean parameter is using a converter, as the WPF framework specifies. For simplicity, we’ll consider the visibility as a boolean “show”/”no-show”: the ability to hide a column by preserving its width (as the Visiblity enum allows) is not supported here.

    /// <summary>
    /// This converter targets a column header,
    /// in order to take its width to zero when
    /// it should be hidden
    /// </summary>
    public class ColumnWidthConverter
        : IValueConverter
    {
        public object Convert(
            object value, 
            Type targetType, 
            object parameter, 
            System.Globalization.CultureInfo culture)
        {
            var isVisible = (bool)value;
            var width = double.Parse(parameter as string);
            return isVisible ? width : 0.0;
        }


        public object ConvertBack(
            object value, 
            Type targetType, 
            object parameter, 
            System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

    }

Upon that, the XAML structure should be modified according, as below shown:

<Window 
    x:Class="ListViewHacking.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ListViewHacking"
    Title="ListView hacking demo" 
    Height="480" Width="900"
    WindowStartupLocation="CenterScreen"
    FontSize="14"
    Background="{StaticResource BG}"
    >
    
    <Grid
        Margin="50,40"
        >
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <StackPanel
            Orientation="Horizontal"
            Grid.Row="0"
            Margin="20,8"
            >
            <CheckBox Content="Show location columns" x:Name="ChkLoc" Margin="20,0" />
            <CheckBox Content="Show contact columns" x:Name="ChkCont" Margin="20,0" />
        </StackPanel>

        <ListView
            ItemsSource="{Binding Path=People, Source={x:Static local:App.Current}}"
            Grid.Row="1"
            x:Name="lvw1"
            >
            <ListView.Resources>
                <local:ColumnWidthConverter x:Key="cvColumnWidth" />
            </ListView.Resources>
            
            <ListView.View>
                <GridView
                    AllowsColumnReorder="False"
                    >
                    <GridViewColumn Header="FirstName" Width="100" DisplayMemberBinding="{Binding Path=FirstName}" />
                    <GridViewColumn Header="LastName" Width="100" DisplayMemberBinding="{Binding Path=LastName}" />

                    <GridViewColumn 
                        Header="Address" 
                        Width="{Binding Path=IsChecked, ElementName=ChkLoc, Converter={StaticResource cvColumnWidth}, ConverterParameter=200}" 
                        DisplayMemberBinding="{Binding Path=Address}" 
                        />
                    <GridViewColumn 
                        Header="City" 
                        Width="{Binding Path=IsChecked, ElementName=ChkLoc, Converter={StaticResource cvColumnWidth}, ConverterParameter=120}" 
                        DisplayMemberBinding="{Binding Path=City}" 
                        />
                    <GridViewColumn 
                        Header="State" 
                        Width="{Binding Path=IsChecked, ElementName=ChkLoc, Converter={StaticResource cvColumnWidth}, ConverterParameter=50}" 
                        DisplayMemberBinding="{Binding Path=State}" 
                        />
                    <GridViewColumn 
                        Header="ZIP"
                        Width="{Binding Path=IsChecked, ElementName=ChkLoc, Converter={StaticResource cvColumnWidth}, ConverterParameter=60}" 
                        DisplayMemberBinding="{Binding Path=ZIP}" 
                        />

                    <GridViewColumn 
                        Header="Phone" 
                        Width="{Binding Path=IsChecked, ElementName=ChkCont, Converter={StaticResource cvColumnWidth}, ConverterParameter=150}" 
                        DisplayMemberBinding="{Binding Path=Phone}" 
                        />
                    <GridViewColumn 
                        Header="Email" 
                        Width="{Binding Path=IsChecked, ElementName=ChkCont, Converter={StaticResource cvColumnWidth}, ConverterParameter=150}" 
                        DisplayMemberBinding="{Binding Path=Email}" 
                        />
                </GridView>
            </ListView.View>
        </ListView>

    </Grid>
</Window>

The demo above shows that there are two checkboxes: one controls the visibility of the “location” info of each person (row), and the second controls the contacts (phone and e-mail).
The visual result is pretty straightforward.

listview2

Conclusion.

The converter-way is the simplest solution we can use to solve the problem of hiding the columns of a gridview. However, there are many other features we can add, and that is what will be explained in the next articles.

Click here to download the sample application.

How to prevent the navigation off a page in WPF

Colonial navigation...
Colonial navigation…
There’s nothing special in this article, but it’s just a tip for those like me are looking for a way to mimic the Windows Store look-and-feel by using WPF.
Among the tons of features there’s a basic one, which allows to properly manage the page navigation, when hosted within a Frame element.
The aim is detecting when the user requests any kind of navigation off the current page viewed, so that the application can intercept and, if applies, prevent the navigation and keeps on the original page.
My deal is to leverage the Modern-UI/Store-styling best ideas, but keeping sticky to WPF. There are many reasons for keep going to code on WPF, rather Store: I really hope the Microsoft guys will think seriously to merge these two technologies in a near future.

The typical scenario.

The “old-school” UI-style mostly mimics a transaction: a dialog/window will open, and it presents a series of controls (textboxes, checkboxes, etc). As long the user won’t press the “OK” button (or the “Apply” one), any modification to the controls is cached by the “form” hosted. That is, if the user presses the “Cancel” button, it’s much like as the dialog weren’t open at all.
However, if you own any Windows Phone device, you’ll notice that most of the settings are applied as the user changes them: there’s no any confirmation, nor a way to “cancel” any modification. The same behavior is present on the “Modern-UI” sections of Windows 8 (i.e. off the Desktop). Same as the phones is WinRT.

Typical Modern-UI style
Typical Modern-UI style

My goal is having the beauty of the page navigation, typical of the Store/Win8 app, but with the ability to give the app some important features such the form cancellation. Since an user might flip to another page in any time, the code needs some (reliable) trick for detecting when the page is being left, and prevent it.
Indeed, the NavigationService object does almost everything for getting you the life easy, but still exists some extras that you have to manage by yourself.

Let’s start from a basic window, which embeds a frame and the navigation bar.

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" 
        Height="350" Width="525"
        WindowStartupLocation="CenterScreen"
        >
    
    <Grid>
        <Frame
            NavigationUIVisibility="Visible"
            x:Name="f1"
            />
    </Grid>
</Window>

In the code behind, as the window loads, a “Page1” instance is created, then placed as content for the frame.

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += MainWindow_Loaded;
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            this.f1.Navigate(new Page1());
        }
    }
}

The “Page1” class looks as follows.

<Page x:Class="WpfApplication2.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
	Title="Page1">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        
        <TextBlock 
            Text="{Binding Path=Title, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Page}}" 
            FontSize="40" 
            Grid.Row="0"
            Margin="20,5"
            />
        
        <CheckBox
            Content="Prevent back browsing"
            x:Name="ChkBack"
            Grid.Row="1"
            HorizontalAlignment="Left"
            VerticalAlignment="Center"
            Margin="10,5"
            />
        
        <Button
            Content="Next page"
            Click="Button_Click_1"
            Grid.Row="1"
            Width="100"
            Height="30"
            HorizontalAlignment="Right"
            Margin="10,5"
            />
    </Grid>
</Page>

…and its code behind…

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for Page1.xaml
    /// </summary>
    public partial class Page1 : Page
    {
        public Page1()
        {
            InitializeComponent();
            this.Loaded += Page1_Loaded;
            this.Unloaded += Page1_Unloaded;
        }

        void Page1_Loaded(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("{0} is loaded", this.Title);
        }

        void Page1_Unloaded(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("{0} is unloaded", this.Title);
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            this.NavigationService.Navigate(new Page2());
        }
    }
}

When run, the app clearly shows the window with the hosted page.

page1

NOTE: For sake of simplicity, in this demo there are three pages almost identical, except for the title’s name, just for distinguish them. For this reason, in some context a control might not have sense. An evident example is about the “prevent back browsing” checkbox for the first page.

Now, the “next page” button should take us to a “Page2”, by creating a brand new instance of this page. This function is supposed having any restriction.

Once the second page has shown, maybe we would like to get back the first one. However, the code should be aware of this, and to demonstrate this, we’ll use the checkbox: when checked the navigation back should be canceled.

page2

What happens to a page when a navigation takes place?

That’s really interesting, because is something different than usually happens for a normal window.
We know that the Loaded event is fired once, when the window completes its creation process and is ready for the interaction. This concept is appliable to any FrameworkElement.
Similarly, the Unloaded event is fired when the instance is being destroyed, or is no more useful.

NOTE: never rely too much on the Unloaded event, because not in any circumstance may be fired.

For a certain Page instance, the Loaded and the Unloaded event may be fired many times along the page life-cycle. Of course, the very first Loaded event is fired whenever the page loads at all, as any other element, but it will be called also any time we navigate back to that page instance, when cached in the journal.
The same consideration applies for the Unloaded event.
So, we can’t rely on the Loaded/Unloaded events for keeping track of the page instance life-cycle: the same instance will survive until the journal trash it, but the events are fired many times.
This is very important, because may lead easily to unpredictable behaviors, when not properly managed.

The “Navigation” event.

As mentioned, the Frame exposes a very useful NavigationService, which manages the actual page flipping, the journal, and also a kind of notification about what is going under the hood. It’s worthwhile noting that the real value of this engine is when the page is loaded asynchronously, for example by an URI.
Here is very simple, and the page is fed directly as element.
As said, the navigation service yields a notification event for alerting any subscriber of the incoming new action requested by the user. This is the Navigating event.

The most straightforward approach is subscribing the event on the Loaded event handler, then unsubscribe it on the Unloaded one. However, seems that there’s no more NavigationService available at the unloading time. So, we must keep a reference in order to properly remove the event callback.

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for Page1.xaml
    /// </summary>
    public partial class Page1 : Page
    {
        public Page1()
        {
            InitializeComponent();
            this.Loaded += Page1_Loaded;
            this.Unloaded += Page1_Unloaded;
        }

        private NavigationService _navsvc;

        void Page1_Loaded(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("{0} is loaded", this.Title);
            this._navsvc = this.NavigationService;
            this._navsvc.Navigating += NavigationService_Navigating;
        }

        void Page1_Unloaded(object sender, RoutedEventArgs e)
        {
            this._navsvc.Navigating -= NavigationService_Navigating;
            this._navsvc = null;
            Console.WriteLine("{0} is unloaded", this.Title);
        }

        void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
        {
            Console.WriteLine("{0} is navigating: {1}", this.Title, e.NavigationMode);
            if (this.ChkBack.IsChecked == true && e.NavigationMode == NavigationMode.Back)
            {
                e.Cancel = true;
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            this.NavigationService.Navigate(new Page2());
        }
    }
}

Honestly, I would have loved to use the weak event pattern, which has a wonderful helper on the latest .Net Framework 4.5 edition. However, for some (unknown) reason, the weak event subscription is not working for this case. I tried to inspect what’s happening behind, but the framework’s code is looking particularly complex.

For those are interested, here is the code of the sample application above described.

How to get our Netduino running faster

Before going on on my graphic library for led matrix, I think it’s time to optimize a bit the code in order to get the Netduino running faster.
My job is programming application using .Net for desktop, but a PC is very rich of resources such as RAM and processor speed. Instead, the Micro Framework offers a very small environment where every byte more might have an impact on the final result.
running_cheetah_320x240
Here is a brief bunch of tests for showing a comparison on different approaches against a same task. Sometime you don’t care about the best way to write the code, but the interesting thing is actually knowing how the things are working. You will be surprised, as I was.

The test bench.

The base program for the tests is very simple: it is an endless loop where the code under test runs interleaved by a short pause of 100ms. The comparison is mostly against different yet commonly-used types, such as Int32, Single, Double and Byte.
The timings are taken by using a scope, then watching at two output ports when they change their state.
Except for the very first, each test cycles 50 times over a 20-operations set: that for minimize the overhead due to the “for-loop”. By the way, the first test is targeted just for get the “for-loop” heaviness.
It follows the test program template:

namespace PerformanceTest
{
    public class Program
    {
        private const int Count = 50;

        private static OutputPort QTest = new OutputPort(Pins.GPIO_PIN_D0, false);
        private static OutputPort QPulse = new OutputPort(Pins.GPIO_PIN_D1, false);


        public static void Main()
        {
            byte b;
            byte bx = 50;
            byte by = 16;

            int i;
            int ix = 50;
            int iy = 16;

            float f;
            float fx = 50.0f;
            float fy = 16.0f;

            double d;
            double dx = 50.0;
            double dy = 16.0;

            while (true)
            {
                //start of the test
                QTest.Write(true);


                // ... operations to test ...


                //end of the test
                QTest.Write(false);
                Thread.Sleep(100);
            }
        }


        private static void Pulse()
        {
            QPulse.Write(true);
            QPulse.Write(false);
        }

    }
}

The basic for-loop.

Since every test will use the “for-loop”, we should measure how much overhead that introduces.
Here is the snippet…

                for (int n = 0; n < 1000; n++)
                {
                    //do nothing
                }

…and here is the timing:
UNIT0000

Roughly speaking, we could say that every for-loop cycle takes about 7 microseconds.

How does look the IL-opcodes generated by the compiler (restricted to the only for-loop)?
Well, it is pretty interesting digging a bit behind (or under?) the scenes. I will take advantage by the awesome ILSpy, which is a free, open-source decompiler, disassembler and much more provided by the SharpDevelop teams.

		IL_0042: ldc.i4.0
		IL_0043: stloc.s n
		IL_0045: br.s IL_004f
		// loop start (head: IL_004f)
			IL_0047: nop
			IL_0048: nop
			IL_0049: ldloc.s n
			IL_004b: ldc.i4.1
			IL_004c: add
			IL_004d: stloc.s n

			IL_004f: ldloc.s n
			IL_0051: ldc.i4 1000
			IL_0056: clt
			IL_0058: stloc.s CS$4$0000
			IL_005a: ldloc.s CS$4$0000
			IL_005c: brtrue.s IL_0047
		// end loop

Notice how the final branch-on-true jumps back to the first opcode, which implies a couple of “nop”s: why?
Anyway, we are not going to optimize the for-loop yet.

Addition.

The addition will be performed over three common types: Int32, Single and Double.
Here is the snippet…

                for (int n = 0; n < Count; n++)
                {
                    i = ix + iy; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    f = fx + fy; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    d = dx + dy; //repeated 20 times
                }

…and here is the timing:
UNIT0001

Again, an “average” addition takes about 2 microseconds.

Many users are blaming the poor speed of a board like Netduino, because its core can run at over 200Mips. Two microseconds for an addition (integer or floating-point) seems a waste of performance, but…please, bear in mind that a so small yet inexpensive board performs similar about the same as an old 1984 IBM PC-AT machine (estimated price US$5000).

The interesting thing is that there’s almost no difference between using Int32 or Single, whose are both 32-bit based. Surprisingly, even choosing Double as type, the calculation takes insignificantly longer than the other cases. However, a Double takes 8 bytes.
Below there are the parts of IL whose depict the operations:

                        // ...

			IL_004e: ldloc.s ix
			IL_0050: ldloc.s iy
			IL_0052: add
			IL_0053: stloc.3
                        
                        // ...

			IL_00eb: ldloc.s fx
			IL_00ed: ldloc.s fy
			IL_00ef: add
			IL_00f0: stloc.s f
                        
                        // ...

			IL_019c: ldloc.s dx
			IL_019e: ldloc.s dy
			IL_01a0: add
			IL_01a1: stloc.s d
                        
                        // ...

Multiplication.

Here is the snippet…

                for (int n = 0; n < Count; n++)
                {
                    i = ix * iy; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    i = ix << 4; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    f = fx * fy; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    d = dx * dy; //repeated 20 times
                }

…and here is the timing:
UNIT0002

As for the addition, the multiplication takes almost the same time to perform and it seems there’s no significant loss of performance over different data types.
There is an extra-special case, which calculates the multiplication leveraging the left-shift operator. It’s a very particular case, but it’s noticeable the better speed than an ordinary multiplication. Is it worthwhile choosing a shift over a real multiplication? I don’t believe…
Below there are the parts of IL whose depict the operations:

                        // ...

			IL_004e: ldloc.s ix
			IL_0050: ldloc.s iy
			IL_0052: mul
			IL_0053: stloc.3
                        
                        // ...

			IL_00e8: ldloc.s ix
			IL_00ea: ldc.i4.4
			IL_00eb: shl
			IL_00ec: stloc.3
                        
                        // ...

			IL_016e: ldloc.s fx
			IL_0170: ldloc.s fy
			IL_0172: mul
			IL_0173: stloc.s f
                        
                        // ...

			IL_021f: ldloc.s dx
			IL_0221: ldloc.s dy
			IL_0223: mul
			IL_0224: stloc.s d
                        
                        // ...

Logical AND.

Here is the snippet…

                for (int n = 0; n < Count; n++)
                {
                    i = ix & iy; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    b = (byte)(bx & by); //repeated 20 times
                }

…and here is the timing:
UNIT0003

It is clear that a logical operation like the AND takes almost the same as an ordinary addition between Int32-s. Instead, the interesting thing is seeing how different is working with Int32 and Byte.
Any .Net Framework operates at least on 32-bits operands (whereas possible it uses 64-bits). Thus, when you constrain your variables to a tiny byte, most operations will cast the values to Int32-s. That takes much more time to do and demonstrates why in the .Net world the speculation habits of small CPUs are wrong.
Below there are the parts of IL whose depict the operations:

                        // ...

			IL_004e: ldloc.s ix
			IL_0050: ldloc.s iy
			IL_0052: and
			IL_0053: stloc.3
                        
                        // ...

			IL_00e8: ldloc.1
			IL_00e9: ldloc.2
			IL_00ea: and
			IL_00eb: conv.u1
			IL_00ec: stloc.0
                        
                        // ...

Min/Max calculation.

Here is the snippet…

                for (int n = 0; n < Count; n++)
                {
                    i = System.Math.Min(ix, iy);
                    i = System.Math.Max(ix, iy);
                    // ... repeated 10 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    i = ix < iy ? ix : iy;
                    i = ix > iy ? ix : iy;
                    // ... repeated 10 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    i = ix; if (ix < iy) i = iy;
                    i = ix; if (ix > iy) i = iy;
                    // ... repeated 10 times
                }

…and here is the timing:
UNIT0005

Please, bear in mind that the time is 5x than the above charts.

Using a library function is preferable: we should avoid “reinventing the wheel” and most of the times a library function embeds native code and yields faster results. However, when that function is particularly simple, it could be better choosing another approach, such as in this example.
The timings clear shows that calling the framework’s Min/Max function takes about three-times than using a trivial ternary-if. Even using a third attempt for calculating the min/max yields no better results other than the most trivial way.
Let’s have a peek at the IL assembly:

                        // ...

			IL_004e: ldloc.s ix
			IL_0050: ldloc.s iy
			IL_0052: call int32 [mscorlib]System.Math::Min(int32, int32)
			IL_0057: stloc.3
                        
                        // ...

			IL_013b: ldloc.s ix
			IL_013d: ldloc.s iy
			IL_013f: blt.s IL_0145

			IL_0141: ldloc.s iy
			IL_0143: br.s IL_0147

			IL_0145: ldloc.s ix

			IL_0147: stloc.3
                        
                        // ...

			IL_0264: ldloc.s ix
			IL_0266: stloc.3
			IL_0267: ldloc.s ix
			IL_0269: ldloc.s iy
			IL_026b: clt
			IL_026d: ldc.i4.0
			IL_026e: ceq
			IL_0270: stloc.s CS$4$0000
			IL_0272: ldloc.s CS$4$0000
			IL_0274: brtrue.s IL_0279

			IL_0276: ldloc.s iy
			IL_0278: stloc.3
                        
                        // ...

Sample expression.

Here is the snippet…

                for (int n = 0; n < Count; n++)
                {
                    d = ix * (fx + dx) * (fy + dy); //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    d = ix; 
                    d *= fx + dx; 
                    d *= (fy + dy);
                    // ... repeated 20 times
                }

…and here is the timing:
UNIT0004

The timings are showing that an inline-expression performs better than a compound operator. That’s normal, because the compiler actually does what the user wrote: store each intermediate operation in the variable. That forces the compiler to avoid optimizations such as in the inline syntax.
The IL opcodes demonstrate the longer task in the second case:

                        // ...

			IL_004e: ldloc.s ix
			IL_0050: conv.r8
			IL_0051: ldloc.s fx
			IL_0053: conv.r8
			IL_0054: ldloc.s dx
			IL_0056: add
			IL_0057: mul
			IL_0058: ldloc.s fy
			IL_005a: conv.r8
			IL_005b: ldloc.s dy
			IL_005d: add
			IL_005e: mul
			IL_005f: stloc.s d
                        
                        // ...

			IL_01ef: ldloc.s ix
			IL_01f1: conv.r8
			IL_01f2: stloc.s d
			IL_01f4: ldloc.s d
			IL_01f6: ldloc.s fx
			IL_01f8: conv.r8
			IL_01f9: ldloc.s dx
			IL_01fb: add
			IL_01fc: mul
			IL_01fd: stloc.s d
			IL_01ff: ldloc.s d
			IL_0201: ldloc.s fy
			IL_0203: conv.r8
			IL_0204: ldloc.s dy
			IL_0206: add
			IL_0207: mul
			IL_0208: stloc.s d
                        
                        // ...

Conclusion.

As a professional programmer, I ma obsessed by well-written source code, patterns, good-practices and so away. However, I also believe it’s useful to know when and how put your finger on a program to get the most from it.
That is also a good programming practice, IMHO.