RSS

Category Archives: .Net

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.

 
Leave a comment

Posted by on July 26, 2014 in .Net, Software

 

Tags: , , , ,

Cet MicroWPF is now on CodePlex

After loooooooong time, the Cet MicroWPF repository is publicly available on CodePlex.
The awaited release comes with a (decent) tutorial, where you may follow step-by-step how to create a nice graphical UI for your Netduino. Many more is still to do, but of sure there are enough stuffs to have some fun!

My Snapshot18

Stay tuned!

 
Leave a comment

Posted by on May 31, 2014 in .Net, Software

 

Tags: , , , , , , ,

Two little “endians”…and then there were none (of big)

1940 cover of the bookIf you don’t have problems, it means that you are doing nothing new. In my job, I do have problems almost everyday, and that’s making me happy!
If you deal with low-level data transfer, then you probably faced the different “endianness” of the processors. Traditionally, companies like Intel embraced the Little-endian choice, whereas Motorola (now Freescale) joined the Big-endian way.
Now, it seems that the .Net Framework cares only the Little-endian vision of the world. Here is an excerpt of the BitConverter class as seen with any decent disassembler:

	public static class BitConverter
	{
		/// <summary>Indicates the byte order ("endianness") in which data is stored in this computer architecture.</summary>
		/// <filterpriority>1</filterpriority>
		[__DynamicallyInvokable]
		public static readonly bool IsLittleEndian = true;

                // ...

Anyway, when you have to write a C#/.Net program which has to exchange data with a Big-endian device, you’re in trouble because the very poor support of this format. So, I created a pretty decent reader/writer pair that should come useful for many of you.

The “BIDI”-way.

Many modern processors supports both the “endiannesses”, so…why a BinaryReader/BinaryWriter shouldn’t act as them? Furthermore, it’s not unusual to see a mixed-format data in the same stream. One of the latest occasions was just on the FT800 chip, which requires a mixture of Big-endian for the addressing, despite the specs state that the chip is Little-endian based.
So, I definitely wanted a Reader/Writer capable of both. However, the interface is meant as “explicit” reference to a type yet the format. There’s no any “default” format, and this context might be interesting as well. The classes have been based by the original Microsoft’s BinaryReader and BinaryWriter, then I modified the data access. The pair of new classes are named as BidiBinaryReader and BidiBinaryWriter.
If any of you browsed the sources of my Modbus library, then the problem isn’t new at all. This time I turned the source to “wrap” a generic Stream object, instead a faster but less-abstract byte array. Here is an example of how the BidiBinaryReader:


        /// <summary>Reads a 4-byte signed integer (Little-endian) from the current stream and advances the current position of the stream by four bytes.</summary>
        /// <returns>A 4-byte signed integer read from the current stream.</returns>
        /// <exception cref="T:System.IO.EndOfStreamException">The end of the stream is reached. </exception>
        /// <exception cref="T:System.ObjectDisposedException">The stream is closed. </exception>
        /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
        /// <filterpriority>2</filterpriority>
        public virtual int ReadInt32LE()
        {
            this.FillBuffer(4);
            return
                (int)this.m_buffer[0] |
                (int)this.m_buffer[1] << 8 |
                (int)this.m_buffer[2] << 16 |
                (int)this.m_buffer[3] << 24;
        }


        /// <summary>Reads a 4-byte signed integer (Big-endian) from the current stream and advances the current position of the stream by four bytes.</summary>
        /// <returns>A 4-byte signed integer read from the current stream.</returns>
        /// <exception cref="T:System.IO.EndOfStreamException">The end of the stream is reached. </exception>
        /// <exception cref="T:System.ObjectDisposedException">The stream is closed. </exception>
        /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
        /// <filterpriority>2</filterpriority>
        public virtual int ReadInt32BE()
        {
            this.FillBuffer(4);
            return
                (int)this.m_buffer[3] |
                (int)this.m_buffer[2] << 8 |
                (int)this.m_buffer[1] << 16 |
                (int)this.m_buffer[0] << 24;
        }

What the classes don’t expose.

The original Microsoft’s sources also offer the support for reading and writing chars, thus the codec-way to manipulate bytes. The problem is that those sources access to several internal stuffs, so the only way to leverage them is via reflection. I usually work with plain byte-arrays, and the text conversion is made by some specific codec (e.g. UTF8Encoding).
As stated, there’s no a support for setting a “default” endinanness of the Reader/Writer. I mean using the same original’s interface, but allowing the user to set whether adopt the Big- instead of the Little-endian format.

So far so well. As usual here are the sources.

 
Leave a comment

Posted by on March 27, 2014 in .Net, Software

 

Tags: , , , ,

Micro-JSON for Netduino (and PC)

JSON logoThis is a pretty useful tool for the Netduino, which I need for playing around some Micro-WPF demo on the Eve board.
As soon you want to deal with web-services, JSON is a must-have format for serializing data. Although Netduino does not use Javascript, the JSON format is very compact, at least when compared to XML. By the way, XML is richer as structure and schema, and JSON is sometimes blurry about the data format (e.g. date and time).
The small software library comes with both a parser and a serializer. The parser rules strictly rely on the specification as in the official JSON portal.
The parser deserializes a JSON string to a DOM of specific objects. I’ve been deeply inspired by the JLinq of the awesome library JSON.Net by James Newton-King.

The problem.

Create a JSON parser isn’t a really complex task, unless you have to work on very-low resources devices. In that case, everything should be optimized at best.
My first attempt to create a decent parser and serializer was successful, but the result was not what I’d expected. Although the code runs surprisingly fast on a normal PC, on the Netduino Plus 2 runs pretty slow and takes a lot (i.e. too much) RAM. That leaded me to adjust and optimized several parts of the code, at least to solve the memory occupation issue. The second release is pretty better.

How it works.

The approach is functional-like, although it’s normal C# highly optimized for low-resources platform. However, the same code works on any .Net platform without any problem.
As stated, the first attempt wasn’t the best one. I used several resource-heavy components, which de-facto prohibits the usage on the Netduino. So, it turned to a different yet trivial solution using as less resources as possible. Not sure that’s the very best achievement possible, though.

For instance, here is the piece of code to parse a JSON string, as used in the first release:

        private static JsonParserContext ConsumeString(
            this JsonParserContext ctx,
            bool throws
            )
        {
            var src = ctx.Source;
            JsonParserContext rtn;
            if ((rtn = ctx.ConsumeWhiteSpace().ConsumeAnyChar("\"", throws)).IsSucceeded)
            {
                var sb = new StringBuilder();

                for (int p = src.Position, len = src.Text.Length; p < len; p++)
                {
                    char c;
                    if ((c = src.Text[p]) == '"')
                    {
                        src.Position = p + 1;
                        break;
                    }
                    else
                    {
                        sb.Append(c);
                    }
                }

                rtn.SetResult(
                    new JValue { BoxedValue = sb.ToString() }
                    );
            }

            return rtn;
        }

Below is how it is the new improved version. Notice that there’s no more the StringBuilder object, and it avoids the creation of new JsonParserContext instances on every call.

        private static JsonParserContext ConsumeString(
            this JsonParserContext ctx,
            bool throws
            )
        {
            if (ctx.ConsumeWhiteSpace().ConsumeAnyChar("\"", throws).IsSucceeded)
            {
                JSonReader src = ctx.Begin();

                for (int p = src.Position, len = src.Text.Length; p < len; p++)
                {
                    if ((src.Text[p]) == '"')
                    {
                        ctx.SetResult(
                            new JValue { BoxedValue = src.Text.Substring(src.Position, p - src.Position) }
                            );

                        src.Position = p + 1;
                        break;
                    }
                }
            }

            return ctx;
        }

Another great improvement (in terms of resource savings) is about the way to store the key-value pairs in a JSON object.
The first attempt uses the Hashtable object, which comes with any .Net platform, and it’s tailored for such purpose. However, its O(1)-access ability comes with a price in terms of resources, and it’s too high to afford for a Netduino.
The more-trivial solution of a simple array requires much less resources, but the data access now takes O(N).

Performance.

I performed the test with several JSON strings. The longest is about 9kiB, while the shortest is roughly 500 bytes.
Using the first release, the longest string is almost impossible to parse: the parser runs out of RAM very quickly.

Here are some results.
In the following picture there is the complete JSON “roundtrip” (parsing+serializing) of the shortest string (about 500 bytes), using the FIRST release.
The upper plot shows the parsing duration (high level) and takes about 170ms to complete. The serialization of the resulting object is way faster and requires a little more than 20ms (lower plot).

UNIT0000

Hereinafter, the charts are all related to the SECOND library release.
Here is the same 500 bytes-string parsed then serialized. Despite on the PC the revision takes a little longer to perform, on the Netduino is a little faster instead. I suppose all the benefits derive from the less RAM usage.

UNIT0001

Here is a 2kiB-JSON parsed, which takes almost 1.2 seconds to perform. The serialzation is not shown here.

UNIT0003

Finally, the “huge” 9kiB-JSON taking looooong to parse: almost 25 seconds!!!. There’s no serialization in this chart, because after a while the Netduino runs out of RAM. I believe there’s something to trim yet…

UNIT0002

The J-DOM.

I don’t know how to call it. The reference JSON.Net library where I inspired from offers a complete DOM support together with Linq, but that’s not possible in a tiny context as the Micro Framework is. By the way, the DOM I defined is JSON-specific: is the result of the serialization, and allows to manipulate the resulting object with ease. Once the DOM is complete, you can serialize it to have back a JSON string.
As stated, a must-have tool for any web-related application.

The usage is very simple and it’s the same as the JSON.Net’s JLinq (except for the Linq!).
Given this sample JSON string (as from Wikipedia):

{
    "firstName": "John",
    "lastName": "Smith",
    "age": 25,
    "address": {
        "streetAddress": "21 2nd Street",
        "city": "New York",
        "state": "NY",
        "postalCode": 10021
    },
    "phoneNumbers": [
        {
            "type": "home",
            "number": "212 555-1234"
        },
        {
            "type": "fax",
            "number": "646 555-4567"
        }
    ]
}

Here is some example of manipulation from within your C# code:

            var jdom = (JObject)JsonHelpers.Parse(s);

            Console.WriteLine((int)jdom["age"]);    //displays 25

            //add a new phone entry
            var jentry = new JObject();
            jentry["type"] = "mobile";
            jentry["number"] = "+39-123-456-7890";

            var jphones = (JArray)jdom["phoneNumbers"];
            jphones.Add(jentry);

            string jtxt = JsonHelpers.Serialize(jdom);
            Console.WriteLine(jtxt);

Okay, take me to the source code…

Here is the link with two complete Visual Studio solutions: both regular .Net and Netduino MF. The source contains also the first release of the parser, although it is not used.

 
2 Comments

Posted by on March 6, 2014 in .Net, Software

 

Tags: , , ,

Netduino + FT800 Eve = MicroWPF

The spare time is few, but step by step the target is getting closer.
It’s a been I’ve started playing around the FTDI FT800 Eve board, and it must admit it is awesome. If you need a quick solution to add a small touch display to your *duino board, the Eve is something you should consider.

EVE image

You know, I love Netduino and C#. That’s because I chose to play with the display using Netduino (Plus 2), and honestly I’d expected a pretty bad performance. Instead, the graphic engine of the Eve can be easily driven via SPI from any board. That is, the SPI on Netduino is fast, very fast.

My goal is creating a small library for helping many users to create small and funny home/hobby projects with the Netduino and the Eve display boards. Since I love the classic WPF, how could I avoid to inspire from them?

Micro WPF

If you know WPF, many concepts would come easier. Otherwise, I recommend to take a look to the documentation, tutorials and whatever you want. Even if you don’t harm with a PC, rather with the Windows Store/Phone APIs, the approach here isn’t too far from.
The “WPF” term for a simple Netduino is clearly abused. Here is just the visual approach, the XAML-like approach to create the UI, and -yes- the same ability to create your own controls: MeasureOverride and ArrangeOverride.
That’s not all.
If you have any visual application in mind with Netduino+Eve (e.g. a climate control, IoT client, etc), then probably you’d need some kind of navigation service across several pages. That’s the most modern UI experience, on every device: PC, tablets, and phones.

I still don’t write what the library will offer, because it’s just something made for fun: for helping hobbists and even students working with a UI on a such small board as Netduino is.
For sure, there are NOT (nor in the future):

  • data binding
  • XAML parsing (the tree has to be created programmatically)
  • styling
  • the remaining 99.99% of regular WPF…

An example of layout

The most versatile yet complex layout control is the Grid, but it seems working fine.
Let’s take this sample XAML:

<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.ColumnDefinitions>
            <ColumnDefinition Width="150" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="2*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <StackPanel
            Grid.Row="0"
            Grid.Column="0"
            x:Name="R0C0"
            Background="Blue"
            />

        <StackPanel
            Grid.Row="0"
            Grid.Column="1"
            x:Name="R0C1"
            Background="DarkGreen"
            />

        <StackPanel
            Grid.Row="0"
            Grid.Column="2"
            x:Name="R0C2"
            Background="Red"
            >
            <Button
                Content="Caption"
                Width="120"
                Height="30"
                Margin="10,5"
                HorizontalAlignment="Center"
                x:Name="B0"
                />
        </StackPanel>


        <StackPanel
            Grid.Row="1"
            Grid.Column="0"
            Grid.ColumnSpan="2"
            x:Name="R1C0"
            Background="LightPink"
            />


        <StackPanel
            Grid.Row="2"
            Grid.Column="1"
            Grid.ColumnSpan="2"
            x:Name="R2C1"
            Background="MediumSlateBlue"
            >
            <Button
                Content="Caption"
                Width="120"
                Height="30"
                Margin="10,5"
                HorizontalAlignment="Center"
                x:Name="B2"
                />
        </StackPanel>

    </Grid>
</Page>

On the regular WPF the result is the following:

sample-wpf

Now, let’s see how to write the same thing on Netduino:

    public class DemoPage2 : PageBase
    {
        protected override void OnCreate(FT800Device dc)
        {
            var btn_prev = new WidgetButton() { Margin = new Thickness(10, 5), Text = "Prev" };
            btn_prev.Click += new EventHandler(btn_prev_Click);

            var btn_next = new WidgetButton() { Margin = new Thickness(10, 5), Text = "Next" };
            btn_next.Click += new EventHandler(btn_next_Click);
            btn_next.HAlign = HorizontalAlignment.Center;

            var grid = new WidgetGridContainer();
            grid.Name = "GRID";

            grid.AddColumnDefinition(150);
            grid.AddColumnDefinition(1, GridUnitType.Star);
            grid.AddColumnDefinition(1, GridUnitType.Auto);

            grid.AddRowDefinition(1, GridUnitType.Star);
            grid.AddRowDefinition(2, GridUnitType.Star);
            grid.AddRowDefinition(1, GridUnitType.Auto);

            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C0";
                ctr.Background = Colors.Blue;
                grid.SetRowCol(ctr, 0, 0);
                grid.Children.Add(ctr);

                ctr.Children.Add(btn_prev);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C1";
                ctr.Background = Colors.DarkGreen;
                grid.SetRowCol(ctr, 0, 1);
                grid.Children.Add(ctr);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C2";
                ctr.Background = Colors.Red;
                grid.SetRowCol(ctr, 0, 2);
                grid.Children.Add(ctr);

                ctr.Children.Add(
                    new WidgetButton() { Name = "B0", Margin = new Thickness(10, 5) }
                    );
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R1C0";
                ctr.Background = Colors.LightPink;
                grid.SetRowCol(ctr, 1, 0, 1, 2);
                grid.Children.Add(ctr);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R2C1";
                ctr.Background = Colors.MediumSlateBlue;
                grid.SetRowCol(ctr, 2, 1, 1, 2);
                grid.Children.Add(ctr);

                ctr.Children.Add(btn_next);
            }

            this.Content = grid;
        }

        void btn_prev_Click(object sender, EventArgs e)
        {
            NavigationService.Instance.GoBack();
        }

        void btn_next_Click(object sender, EventArgs e)
        {
            NavigationService.Instance.Navigate(new DemoPage3());
        }
    }

That leads the following snapshot:

My Snapshot5

NOTE: by live the display shows the colors correctly. However, the picture taken renders a bad result.

Widgets, widgets, widgets…

The Eve board is very well designed, because it’s plenty of useful widgets. I don’t believe you’d need something different from the provided.
At the moment of writing, the Netduino library supports:

  • (normal) Button
  • ToggleButton
  • TextBlock
  • Slider
  • Dial

and, as for the layout control:

  • StackPanel
  • Grid

As long the spare time helps me, I will try to add some other useful component as the TextBox and the Image.

Yet some screens generated by the Netduino and the FT800 Eve board.
WP_000595

My Snapshot4

My Snapshot3

My Snapshot7

Source code

I will release a beta release soon.

 
4 Comments

Posted by on February 16, 2014 in .Net, Electronics, Software

 

Tags: , , , , , , , , , , ,

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#!

 
Leave a comment

Posted by on January 19, 2014 in .Net, Software

 

Tags: , ,

WPF editable ComboBox and its weird bug

This is a double-purpose post: a simple hack around the WPF ComboBox, and a subtle bug in it.
The short video explains both the problems way better than my words could do.

Most of the times, I use the ComboBox as a simple drop-down list. That works perfectly and that’s why I never bumped against the problems around.
This time I needed a real ComboBox, that is the ability to select from a drop-down list as always, but with the editable box as well. More precisely, I wanted the following behaviors:

  1. the user can drop the list and select any item (that’s the usual feature)
  2. the user can type in an existent item or a new one
  3. as the user type in the selection box, the drop-down should open
  4. (future) the drop-down list should be filtered upon the actual text typed in the selection box

The first two points are already available in the standard ComboBox control, while the fourth is just a wish for the (near) future. The problems arose with the third point, because the simplest yet intuitive way I used yielded a nice exception!

The base for the test.

Nothing fancy here: just a collection of objects, very simple. The classic “Person” with an “ID” (why didn’t I named so?):

    public class MyItem
    {
        public string Code { get; set; }
        public string Description { get; set; }

        public override string ToString()
        {
            return this.Code;
        }
    }

The data-set generation looks as follows:

    public partial class App : Application
    {
        public IEnumerable<MyItem> ItemCollection { get; private set; }


        protected override void OnStartup(StartupEventArgs e)
        {
            var nomi = new[] { "Mario", "Carlo", "Lucia", "Elena", "Giorgio", "Nicoletta" };
            var cognomi = new[] { "Bianchi", "Rossi", "Verdi", "Brambilla", "Scarpa", "Zennaro" };

            var items = new List<MyItem>();

            for (int i = 0; i < cognomi.Length; i++)
            {
                for (int k = 0; k < nomi.Length; k++)
                {
                    var mi = new MyItem();
                    mi.Code = (i * 10 + 11 + k).ToString();
                    mi.Description = nomi[k] + " " + cognomi[i];
                    items.Add(mi);
                }
            }

            this.ItemCollection = items;

            base.OnStartup(e);
        }
    }

The deal is populating the combo-box with such a data-set, then testing for a numeric input so that the drop-down part should arrange accordingly. As a (future) bonus, the list should be filtered upon the actual number. That should facilitate the user when he/she has to enter a non-existent ID.
On the XAML-side the base is something like this:

<Window 
    x:Class="ComboEditableDemo.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ComboEditableDemo"
    Title="Window1 - buggy" 
    Height="300" 
    Width="400"
    x:Name="This"
    >
    
    <Window.Resources>
        
        <DataTemplate x:Key="dtplItem">
            <StackPanel
                Orientation="Horizontal"
                >
                <TextBlock Text="{Binding Path=Code}" Margin="0,0,8,0" />
                <TextBlock Text="{Binding Path=Description}" />
            </StackPanel>
        </DataTemplate>
        
    </Window.Resources>
    
    <Grid>
        <ComboBox
            x:Name="Cbo1"
            Width="250"
            Height="30"
            IsEditable="True"
            StaysOpenOnEdit="True"
            ItemTemplate="{StaticResource dtplItem}"
            FontSize="18"
            SelectedItem="{Binding Path=CurrentItem, ElementName=This}"
            Text="{Binding Path=CurrentText, ElementName=This}"
            . . .
            >
        </ComboBox>
    </Grid>
</Window>

Finally, here is a possible way to link the data-set to a ComboBox:

            this.Cbo1.ItemsSource = ((App)App.Current).ItemCollection;

First attempt: the bug.

The first attempt was done via a simple styling of the ComboBox, since it exposes two interesting properties:

The style was defined as follows:

        <Style x:Key="ComboStyleKey" TargetType="ComboBox">
            <Setter Property="StaysOpenOnEdit" Value="True" />

            <Style.Triggers>
                <Trigger Property="IsSelectionBoxHighlighted" Value="True">
                    <Setter Property="IsDropDownOpen" Value="True" />
                </Trigger>
            </Style.Triggers>
        </Style>

Although everything seemed going fine (no errors), once you click with the left mouse button in the selection box, a nasty “StackOverflow” exception is suddenly raised. No matter whether the application is creates as “Debug” or “Release”: the error seems very stable.

stack-overflow

At first glance it’s not clear why it happens, and not how to solve or even around it. Also because the actual exception looks as raised in a very deep layer, below the managed. However, that’s just what I suppose.
The second attempt gave me a clearer idea.

Second attempt: better, but not solved yet.

The second attempt was focus on find any (decent) workaround to the bug. Internet didn’t give more help, so I had to find something reliable to make the ComboBox working.
The hint was just on the “stack overflow”, because most of the times it’s a recursive problem. Again, many times you generate such a exception when there are circular calls, that fill the stack sooner. So, let’s give the UI a “breath”: a small delay, so that a routine can complete before actually calling the next one.
Here is the trick:

    public class ComboBox2
        : ComboBox
    {
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);

            if (e.Property.Name == "IsSelectionBoxHighlighted" &&
                this.IsEditable &&
                this.IsSelectionBoxHighlighted &&
                this.IsDropDownOpen == false &&
                this.StaysOpenOnEdit)
            {
                this.OpenDropDown();
            }
        }


        private async void OpenDropDown()
        {
            await Task.Delay(200);
            this.IsDropDownOpen = true;
        }

    }

Well, the exception wasn’t raised any more, but…AW!…the interaction result was not the expected.
Since the drop-down part is actually a borderless “Window” object, it tries to capture the mouse, at least until some kind of mouse action is worthwhile to be captured. As soon, the mouse click outside its client area, the down-down window closes, but the click is “lost”. That is, there’s no (easy) way to interact with the “real” window, so even an attempt to close the application looks impossible.

Despite this trick did not solved the problem, at least it clears *why* the exception is raised in the previous scenario. As soon the selection box is highlighted, the trigger starts the opening of the drop-down. However, the opening of this new child-window would captures the user-input, moving the focus off the selection box. However, the focus is restored to the selection box, and the condition will trigger again the drop-down opening.

Third attempt: all right!

The final solution isn’t much different than the previous attempt: simply avoid the “IsSelectionBoxHighlighted” property…

    public class ComboBox3
        : ComboBox
    {

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);

            if (this.IsEditable &&
                this.IsDropDownOpen == false &&
                this.StaysOpenOnEdit)
            {
                this.IsDropDownOpen = true;
            }
        }

    }

Conclusion.

You may download the source for the demo application here.

 
Leave a comment

Posted by on January 15, 2014 in .Net, Software

 

Tags: , , , ,

Hacking the WPF GridView – Two more features

This is another post about the hacking of the standard WPF GridView typically used with(in) the ListView. If you missed anything about my previous three article on it, please have a look here.
By using the hacked component in some real projects, I discovered that something was missing, and something else could be improved. In particular, here are a couple of features making my GridViewEx almost complete (well…not perfect yet!)

XAML-defined columns.

The GridViewEx approach was based on a GridViewColumn wrapper. The host application should add as many wrappers as needed, and the real columns will be created (and synchronized) accordingly. This approach is basically the MVVM pattern, and yields the ability to manipulate the visual columns with ease and flexibility.
However, that’s not always an acceptable usage: the XAML-way to define templates and styles is far better than the classic code. Well, I wished to find a solution as a compromise between the MVVM flexibility and the XAML power.
The solution I chose is pretty easy: an extra columns “back” synchronization, which operates when there’s no ambiguity between the XAML and the MVVM collections content. The legacy MVVM columns management is still alive and full compatible. However, when the MVVM is bound “empty” the XAML columns definition will be taken in account.
Here follows the code added to the GridViewEx class.

        /// <summary>
        /// Provides the backward-alignment from the XAML-defined columns
        /// to the wrapper collection source.
        /// That should happen only when the source collection is empty,
        /// and there are XAML-column defined in the view.
        /// </summary>
        /// <param name="source"></param>
        private void BackAlign(Collection<GridViewColumnWrapper> source)
        {
            if (source.Count == 0 &&
                this.Columns.Count > 0)
            {
                foreach (GridViewColumn column in this.Columns)
                {
                    var wrapper = new GridViewColumnWrapper();
                    wrapper.Header = column.Header;
                    wrapper.Width = column.Width;
                    wrapper.IsVisible = true;
                    wrapper.ColumnHash = column.GetHashCode();
                    source.Add(wrapper);

                    //setup the column
                    this.SetupColumn(wrapper, column);
                }
            }
        }

The above method is called once only, at the moment of the binding to a new wrapper collection. As the code shows, if there’s no wrappers, the defined XAML GridViewColumn are automatically converted to wrappers. Hereinafter the game plays as usual.

The column’s setup has been moved off the existent Align method, to a dedicated one in order to be used both in the forward- and in the back-alignment of the columns’ collection.

        /// <summary>
        /// Prepares the column binding it to the wrapper
        /// </summary>
        /// <param name="wrapper"></param>
        /// <param name="col"></param>
        private void SetupColumn(
            GridViewColumnWrapper wrapper,
            GridViewColumn 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;
        }

To test the new feature, the window’s XAML page has been simplified as follows.

<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}"
    >
    
    
    <Window.Resources>
        
        <DataTemplate x:Key="dtpl1">
            <TextBlock
                Text="{Binding Path=FirstName}"
                />
        </DataTemplate>


        <DataTemplate x:Key="dtpl2">
            <TextBlock
                Text="{Binding Path=LastName}"
                />
        </DataTemplate>


        <DataTemplate x:Key="dtpl3">
            <TextBlock
                Text="{Binding Path=City}"
                />
        </DataTemplate>

    </Window.Resources>
    
        
    <Grid
        Margin="50,40"
        >
        <ListView
            ItemsSource="{Binding Path=People, Source={x:Static local:App.Current}}"
            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=.}"
                    >
                    <GridViewColumn Header="FirstName" Width="150" CellTemplate="{StaticResource dtpl1}" />
                    <GridViewColumn Header="LastName" Width="150" CellTemplate="{StaticResource dtpl2}" />
                    <GridViewColumn Header="City" Width="150" CellTemplate="{StaticResource dtpl3}" />
                </local:GridViewEx>
            </ListView.View>
        </ListView>
        
    </Grid>
</Window>

Now, let’s switch to the trickier problem.

Per-column defined cell content alignment.

Sometime is useful to define the alignment (horizontal and vertical) of a cell content. Unfortunately the native GridView offers no help about this feature, and the only way to control the cell behavior is via the ListViewItem styling.
To be clear, none of the below approaches will align the text content to the right edge of the respective cells.

        <DataTemplate x:Key="dtpl1">
            <TextBlock
                Text="{Binding Path=FirstName}"
                Background="Yellow"
                HorizontalAlignment="Right"
                />
        </DataTemplate>
        
        <DataTemplate x:Key="dtpl2">
            <TextBlock
                Text="{Binding Path=LastName}"
                Background="Yellow"
                TextAlignment="Right"
                />
        </DataTemplate>

lh5-1

That’s because the template-created content is actually hosted in a ContentPresenter object. The GridView creates as many ContentPresenters as the columns are, and the user’s control over these components is very limited. Please note that the ContentPresenters are created always but when you bind the cell’s content via a simpler DisplayMemberBinding. In that case, a simple TextBlock is created instead.
As said, the only way to control the alignment of the hosted ContentPresenters is by settings the HorizontalContentAlignment (or VerticalContentAlignment) in the ListViewItem style. In other words, you could style the rows as follows:

        <ListView
            ItemsSource="{Binding Path=People, Source={x:Static local:App.Current}}"
            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>

                <!-- alter the items (rows) implicit style -->
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Right" />
                </Style>
            </ListView.Resources>

            <ListView.View>
                <local:GridViewEx
                    AllowsColumnReorder="False"
                    ColumnsSource="{Binding Path=.}"
                    >
                    <GridViewColumn Header="FirstName" Width="150" CellTemplate="{StaticResource dtpl1}" />
                    <GridViewColumn Header="LastName" Width="150" CellTemplate="{StaticResource dtpl2}" />
                    <GridViewColumn Header="City" Width="150" CellTemplate="{StaticResource dtpl3}" />
                </local:GridViewEx>
            </ListView.View>
        </ListView>

The result is as expected, but involves all the cells, without any control on a specific column.

lh5-2

This behavior is predefined in the GridViewRowPresenter, which is part of the default rows styling. The most straightforward way to take the control over the row’s cell presenters is creating (or deriving) a custom GridViewRowPresenter, then re-styling the ListViewItem. However, I would avoid to touch any of the Windows’ default styles.

The solution I used takes advantage of a couple of Attachable DependencyProperty: one for each alignment orientation.
The attached DP comes in aid because it can be stuck anywhere in the logical tree, and that’s helping to reach the hidden visual element. The basic idea is right on the attaching event of the DP: at that time the visual tree is walked up, up to the “original” GridViewRowPresenter. The immediate-child of that presenter is the sought ContentPresenter, and the alignment properties are fully exposed.

        #region DPA HorizontalContainerAlignment

        public static readonly DependencyProperty HorizontalContainerAlignmentProperty = DependencyProperty.RegisterAttached(
            "HorizontalContainerAlignment",
            typeof(HorizontalAlignment),
            typeof(GridViewEx),
            new UIPropertyMetadata(
                default(HorizontalAlignment),
                HorizontalContainerAlignmentChanged
                ));


        public static HorizontalAlignment GetHorizontalContainerAlignment(DependencyObject obj)
        {
            return (HorizontalAlignment)obj.GetValue(HorizontalContainerAlignmentProperty);
        }


        public static void SetHorizontalContainerAlignment(DependencyObject obj, HorizontalAlignment value)
        {
            obj.SetValue(HorizontalContainerAlignmentProperty, value);
        }


        private static void HorizontalContainerAlignmentChanged(object sender, DependencyPropertyChangedEventArgs args)
        {
            var current = sender as DependencyObject;
            int levels = 10;

            while (current != null && levels-- > 0)
            {
                var next = VisualTreeHelper.GetParent(current);
                if (next is GridViewRowPresenter)
                {
                    var cp = current as ContentPresenter;
                    if (cp != null)
                    {
                        cp.HorizontalAlignment = (HorizontalAlignment)args.NewValue;
                    }
                    break;
                }

                current = next;
            }
        }

        #endregion

And here is how to apply it:

        <DataTemplate x:Key="dtpl1">
            <TextBlock
                Text="{Binding Path=FirstName}"
                Background="Yellow"
                local:GridViewEx.HorizontalContainerAlignment="Stretch"
                />
        </DataTemplate>


        <DataTemplate x:Key="dtpl2">
            <TextBlock
                Text="{Binding Path=LastName}"
                Background="Yellow"
                local:GridViewEx.HorizontalContainerAlignment="Right"
                />
        </DataTemplate>


        <DataTemplate x:Key="dtpl3">
            <TextBlock
                Text="{Binding Path=City}"
                Background="Yellow"
                />
        </DataTemplate>

Finally, the visual result is the following.
lh5-3

Conclusions.

Hacking. Far funnier than digging around for hours looking for a ready-to-go solution, which (we do know) does not exist.
I loved this series of hacking around the GridView, because it showed me that even a very simple component as the (ListView plus the) GridView is, yields a lot of power by just learning a bit on how its core works.

Feel free to download the demo source here.

 
Leave a comment

Posted by on November 10, 2013 in .Net, Software

 

Tags: , , ,

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 string1.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 string1.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.

 
Leave a comment

Posted by on August 17, 2013 in .Net, Software

 

Tags: , ,

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.

 
2 Comments

Posted by on August 11, 2013 in .Net, Software

 

Tags: , , ,

 
Follow

Get every new post delivered to your Inbox.

Join 86 other followers