Thrash505’s Code Blog

February 4, 2010

WpfSplitButton discontiued…

Filed under: C#, WPF — Tags: , , — thrash505 @ 3:20 pm

I just wanted to inform anyone looking into my WpfSplitButton control, that I have not been working on it since my last post about it and I do not have any plans of continuing with it. Hopefully it will serve as a good starting point for other developers. I must admit that it is not a long-term solution and should not be used in any final product. Although the code is yours to modify, extend, and use anyway you feel necessary.

C# CodeGenerationHelper – Dynamic Classes – Create Class From Hashtable at Run-time

Filed under: C#, WPF, Windows Forms — Tags: , , , , , — thrash505 @ 3:06 pm

Overview
Back a few months ago I had a class that needed (or so I thought) to be generated at run-time. The need arose from WPF controls only working with Properties, not fields, and more specifically ones that implemented INotifyPropertyChanged. (or dependency properties, but I typically save those for custom controls) After some research I created a simple straightforward helper class, CodeGenerationHelper, that would create a dynamic class at run-time from a hashtable. From a hashtable because my solution was working with data received through XML-RPC in the from of an extended hastable implementation. (XmlRpcStruct)

CodeGenerationHelper.cs Listing:

using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections;
using System.IO;
using Microsoft.CSharp;

namespace CodeGenerationTest
{
    public static class CodeGenerationHelper
    {
        /// <summary>
        /// Creates a dynamic class in memory from a hashtable. Each entry in the hashtable will become a field
        /// with a corresponding property. The class will implement INotifyPropertyChanged for each of the
        /// properties.
        /// </summary>
        /// <param name="namespaceName">The name of the namespace that will contain the dynamic class.</param>
        /// <param name="className">The name of the dynamic class.</param>
        /// <param name="source">The source hashtable that the members of the dynamic class will based off of.</param>
        /// <param name="useKeysForNaming">If set to True, the keys of the hashtable will be converted to strings
        /// and the field names and property names of the dynamic class will be based off of those strings. If
        /// set to false, the fields and properties will be named in sequential order.</param>
        /// <returns>Returns the C# code as a string.</returns>
        public static string CreateClassFromHashtable(string namespaceName, string className, Hashtable source,
            bool useKeysForNaming)
        {
            // Create compile unit.
            CodeCompileUnit compileUnit = new CodeCompileUnit();

            // Create namespace.
            CodeNamespace dynamicNamespace = new CodeNamespace(namespaceName);
            dynamicNamespace.Imports.Add(new CodeNamespaceImport("System.ComponentModel"));

            // Create class.
            CodeTypeDeclaration dynamicClass = new CodeTypeDeclaration(className);
            dynamicClass.IsClass = true;
            dynamicClass.BaseTypes.Add(new CodeTypeReference("System.ComponentModel.INotifyPropertyChanged"));

            // Create PropertyChanged event; implement INotifyPropertyChanged.
            CodeMemberEvent propertyChangedEvent = new CodeMemberEvent();
            propertyChangedEvent.Name = "PropertyChanged";
            propertyChangedEvent.Type = new CodeTypeReference("System.ComponentModel.PropertyChangedEventHandler");
            propertyChangedEvent.Attributes = MemberAttributes.Public;
            dynamicClass.Members.Add(propertyChangedEvent);

            foreach (object key in source.Keys)
            {
                // Construct field and property names.
                string fieldName = string.Format("_{0}", key.ToString());
                string propertyName = key.ToString();

                // Create field.
                CodeMemberField dynamicField = new CodeMemberField(source[key].GetType(), fieldName);
                dynamicField.InitExpression = new CodePrimitiveExpression(source[key]);
                dynamicClass.Members.Add(dynamicField);

                // Create property.
                CodeMemberProperty dynamicProperty = new CodeMemberProperty();
                dynamicProperty.Name = key.ToString();
                dynamicProperty.Type = new CodeTypeReference(source[key].GetType());

                // Create property - get statements.
                dynamicProperty.GetStatements.Add(new CodeMethodReturnStatement(
                    new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName)));

                // Create property - set statements.
                // Assign value to field.
                dynamicProperty.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(
                    new CodeThisReferenceExpression(), fieldName), new CodePropertySetValueReferenceExpression()));

                // Call PropertyChanged event.
                // Create target object reference.
                CodeEventReferenceExpression propertyChangedTargetObject = new CodeEventReferenceExpression(
                    new CodeThisReferenceExpression(), "PropertyChanged");

                // Create parameters array.
                CodeExpression[] propertyChangedParameters = new CodeExpression[]
                {
                    new CodeThisReferenceExpression(),
                    new CodeObjectCreateExpression("System.ComponentModel.PropertyChangedEventArgs",
                        new CodeExpression[] { new CodePrimitiveExpression(propertyName) })
                };

                // Create delegate invoke expression and add it to the property's set statements; call PropertyChanged.
                CodeDelegateInvokeExpression invokePropertyChanged = new CodeDelegateInvokeExpression(
                    propertyChangedTargetObject, propertyChangedParameters);
                dynamicProperty.SetStatements.Add(invokePropertyChanged);

                // Add property to class.
                dynamicClass.Members.Add(dynamicProperty);
            }

            // Add class to namespace.
            dynamicNamespace.Types.Add(dynamicClass);

            // Add namespace to compile unit.
            compileUnit.Namespaces.Add(dynamicNamespace);

            // Generate CSharp code from compile unit.
            StringWriter stringWriter = new StringWriter();
            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
            provider.GenerateCodeFromCompileUnit(compileUnit, stringWriter, new CodeGeneratorOptions());
            stringWriter.Close();
            return stringWriter.ToString();
        }

        public static object InstantiateClassFromCodeString(string codeString, string fullyQualifiedTypeName)
        {
            CSharpCodeProvider compiler = new CSharpCodeProvider();
            CompilerParameters compilerParams = new CompilerParameters(new string[] { "System.dll" });
            CompilerResults results = compiler.CompileAssemblyFromSource(compilerParams, new string[] { codeString });
            return results.CompiledAssembly.CreateInstance(fullyQualifiedTypeName);
        }
    }
}

Now I’m not going to run through the details of how the class works, but I believe that it is well commented enough that with a little research it is easily understandable. I will demonstrate an example of how the class can be used.

Example Usage:

Hashtable rawCustomer = new Hashtable();
rawCustomer["Id"] = 123456789;
rawCustomer["FirstName"] = "Billy";
rawCustomer["LastName"] = "Bob";
rawCustomer["Rating"] = 84.5D;

string customerCode = CodeGenerationHelper.CreateClassFromHashtable("CodeGenerationTest", "Customer",
    rawCustomer, true);
object customer = CodeGenerationHelper.InstantiateClassFromCodeString(customerCode, "CodeGenerationTest.Customer");

Now there isn’t much to this example simply because that’s as far as I’ve gone with it. I’m sure that it has many possible uses, but I will caution you about going down this route in the first place. A much better solution then generating code at run-time likely exists that will solve your particular problem. For me it was creating a DataTable from the hashtables I received from XML-RPC (for some reason this seems to work at least with the WPF DataGrid, I haven’t tried anything else as of yet). My point is I believe this is going into potentially dangerous areas and you should use this code generation method only as a last resort.

Okay, enough of that and back to the example. First you can see that I create a hashtable and fill it with name/value pairs. Notice though the Rating entry: it has a D suffix at the end of its value to force a type of double. When the code generation is executed this will be respected and enforced as you can see in the output below. Suffixes exist for each of the built-in value types and you can easily find them out with a little bit of research. (although I can’t recall what their formally referred to…) Next I pass the hashtable into the CreateClassFromHashtable method and I get back a complete string representation of our to-be dynamic class. (The output is shown in the section below) Finally we create an instance of our dynamic class. Now this is a very straight forward example and implementation, but I believe the information here provides a good starting point. If I end up continuing down the code generation path I will share my findings, and encourage others to do the same.

Example Output:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.3603
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace DataGridTest {
    using System.ComponentModel;

    public class Customer : System.ComponentModel.INotifyPropertyChanged {

        private double _Rating = 84.5;

        private string _LastName = "Bob";

        private int _Id = 123456789;

        private string _FirstName = "Billy";

        private double Rating {
            get {
                return this._Rating;
            }
            set {
                this._Rating = value;
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("Rating"));
            }
        }

        private string LastName {
            get {
                return this._LastName;
            }
            set {
                this._LastName = value;
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("LastName"));
            }
        }

        private int Id {
            get {
                return this._Id;
            }
            set {
                this._Id = value;
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("Id"));
            }
        }

        private string FirstName {
            get {
                return this._FirstName;
            }
            set {
                this._FirstName = value;
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("FirstName"));
            }
        }

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    }
}

July 9, 2009

WpfSplitButton – Version 1.0.0.2 (coming soon…)

Filed under: C#, WPF — Tags: , , , — thrash505 @ 2:49 pm

I’ve started to use my WpfSplitButton control in one of my projects and I’m discovering some difficulties and/or inconveniences with it. I’m now resolving some of those issues and will release an update in a few days.

(more…)

WPF – Selector/ListBox/ListView/TabControl – Auto-Select First Item Using XAML

Filed under: C#, WPF — Tags: , , , , , — thrash505 @ 1:31 pm

When your application has a control on it that derives from Selector and has no items on load nothing is selected, obviously. During run-time when the user is clicking around and adds items to the Selector-derived control, you would assume that the control would automatically select the first item because that only makes sense. However, your assumption and mine would be wrong; this is not the behavior at all. Instead the selector will still have no items selected. This means in order to get this “Auto-select first item” behavior, you have to do it yourself. I’ve came up with a simple solution to this problem using only XAML.

(more…)

July 6, 2009

WpfMessageBar – Version 1.0.0.0 Released on CodePlex

Filed under: C#, WPF — Tags: , , , — thrash505 @ 4:31 pm

I’ve always disliked dialog boxes… especially ones that only have an “OK” button on it. These sorts of dialog boxes are not very helpful because they stop the user in there tracks to tell them something and then force them to click “OK”. I really don’t like that scenario so I came up with an alternative method of accomplishing the same thing in what I think is a better way.

Its called a message bar and by default it sits on the bottom of a window where the status bar would normally be. When the program needs to subtly tell the user something and the user doesn’t have to make an immediate decision, you can use the message bar. It is not meant for letting the user take an action… so no “Do you want to save?” scenarios. I like this approach better because it still draws attention, but doesn’t stop the user from what there trying to do. Use it when saving to a file failed, when there network connection drops, when they entered an invalid value, etc.

All the details, source code, samples, and screenshots can be found at: http://wpfmessagebar.codeplex.com/

June 24, 2009

WPF SplitButton – Version 1.0.0.1 Released on CodePlex

Filed under: C#, WPF — Tags: , , , — thrash505 @ 11:04 am

I’ve released version 1.0.0.1 of the SplitButton control for WPF on CodePlex: http://anothersplitbutton.codeplex.com/ The details of the changes can be found there or on my previous post as well. If you have any suggestions for the control please feel free to express them on the CodePlex site.

June 22, 2009

WPF SplitButton Update

Filed under: C#, WPF — Tags: , , , — thrash505 @ 12:24 pm

I added a new DependencyProperty for the SplitButtonHeader control called PastLeftDetection. When set to True, any MouseDown past the left of the drop-down initiator (but still on the SplitButton), will cause it to re-route the MouseDown to the DropDownInitiator instead. This will now be the default behavior for SplitButtonHeader because it gives the user their intended result. Also, there are now XML comments for basically everything in the project now.

I’ll release an update on CodePlex in the next few days. If you need the update now, just add a comment to this post or on CodePlex.

June 19, 2009

WPF SplitButton control release on CodePlex

Filed under: C#, WPF — Tags: , , , — thrash505 @ 3:46 pm

I’ve been working on a WPF SplitButton control for the past few days and I finally have a stable, open source, lookless version available on CodePlex. The project and all details can be found here: http://anothersplitbutton.codeplex.com/

June 12, 2009

ArrayCasting Helper Class

Filed under: C# — Tags: , , — thrash505 @ 11:09 am

I’ve found myself in the situation where I have an array of objects that I want to cast into an array of some other type. You’d think that this would be as simple as: (TheType[])objectArray, but unfortunately, one way or another, you have to loop through each object and cast it into the new type. This becomes a pain when you need to do it frequently.

(more…)

May 21, 2009

Frame-Based Animation In WPF

Filed under: C#, WPF — Tags: , , , — thrash505 @ 5:32 pm

Introduction

In WPF most animations are time-based, using storyboards to animate a objects properties over a certain period of time. That is great and works well, until an artist hands you a stack of images that are to be used as individual frames of an animation. This is my current situation, so I spent an hour or two trying to figure out a way to accomplish frame-based animations in WPF. This is what I came up with…

(more…)

Blog at WordPress.com.