Category Archives: C#

F#– WPF Component Development

This post will only deal about using F# for WPF custom component development; it is considered that the user has already knowledge about WPF custom control development.

The current F# support for VS2010 is lagging in some ways,

· Can’t create a folder, this directly affects the way we can define the generic.xaml file.

· XAML -> BAML conversion with MSBuild task

We can do workarounds in both the cases and make component development using F# language and that is what we are going to discuss here. If there is any other better way to go for it, do let me know in your comments.

Creating Folders in an F# project

Till the F# team include this support in VS2010 we need to do the below workaround,

· Edit the .fsproj in Notepad.

· Add the below line in <ItemGroup>

.fsproj code

<Resource Include="Themes\generic.xaml" />

<Compile Include=”NewFolder\somefile.fs” />

XAML to BAML conversion through code

WPF has an API Application.LoadComponent(Uri) which loads a resource, although it is a bit slow. For a WPF component to load its inner template, it requires the generic.xaml file to be loaded when the control is initialized. In WPF C# custom control library, the below code does that automatically,

C# Code

public class CustomControl1 : Control

{

static CustomControl1()

{

DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));

}

}

Or we can just have the DefaultStyleKey overridden in the constructor,

C# Code

public class CustomControl1 : Control

{

public CustomControl1()

{

this.DefaultStyleKey = typeof(CustomControl1);

}

}

F# Solution

BAML conversion doesn’t work in F# because the MSBuild targets project for F# has issues when building the generic.xaml as a “Page” element.

On further investigation, I found that we can manually do the steps through code and make the control apply the template defined in XAML. Below are the steps that needs to be done,

1. Override the “DefaultStyleKey” property,

do this.DefaultStyleKey <- typeof<WatermarkTextBox>

2. Load the resource file and merge it to the control’s resources collection,

let resourceDict = Application.LoadComponent(new Uri("/FSharp.SampleControls.Wpf;component/Themes/generic.xaml", System.UriKind.Relative)) :?> ResourceDictionary

do this.Resources.MergedDictionaries.Add(resourceDict)

This will ensure that the control template is implicitly set to the control, you also have the OnApplyTemplate() getting called when you override that method. That’s it; we have loaded the control template and enabled the custom control to load like a normal WPF component. I also tested by editing the control’s Style using Blend and that also worked,

clip_image002

The full test sample is available in this link. The project contains a simple implementation of a WatermarkTextBox as a WPF custom control; it also has a C# WPF application that uses it.

I have also prepared a simple F# WPF custom control library project, You can download that from this link. You have to place this in the “Project Templates” location,

Windows 7

C:\Users\{UserName}\Documents\Visual Studio 2010\Templates\ProjectTemplates

This should enable VS2010 to load the template.

‘case like classes’ in C# 4.0

 

“case classes” are a notion in scala. It provides an easier syntax to quickly create POJO objects (Its POCO – Plain Old CLR Objects, in .NET). When I first looked at this couple of days back, I was sure this could done with C# too. Here is what I checked,

  • Use dynamic keyword from C# 4.0
  • Create a simple key/value pair to define the property bag values.
  • Construct a dynamic object based on these values.

This looks pretty straight forward. The code is very simple, the CaseClass <- (dervies from) DynamicObject, and keeps a simple key/value pair mapping.

public class CaseClass : DynamicObject
    {
        private Dictionary<string, object> members;
        public CaseClass(IDictionary<string, object> propertyValues)
        {
            this.members = new Dictionary<string, object>();
            foreach (var kvp in propertyValues)
            {
                if (!this.members.ContainsKey(kvp.Key))
                {
                    this.members.Add(kvp.Key, kvp.Value);
                }
            }
        }

        public CaseClass Extends(CaseClass parent)
        {
            var instance = new CaseClass(this.members);
            foreach (var kvp in parent.members)
            {
                if (!instance.members.ContainsKey(kvp.Key))
                {
                    instance.members.Add(kvp.Key, kvp.Value);
                }
                else
                {
                    throw new InvalidOperationException("child object contains the same property key " + kvp.Key);
                }
            }

            return instance;
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (this.members.ContainsKey(binder.Name))
            {
                result = this.members[binder.Name];
                return true;
            }
            else
            {
                return base.TryGetMember(binder, out result);
            }
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            if (!this.members.ContainsKey(binder.Name))
            {
                this.members.Add(binder.Name, value);
            }
            else
            {
                this.members[binder.Name] = value;
            }
            return true;
        }

        public override IEnumerable<string> GetDynamicMemberNames()
        {
            return this.members.Keys;
        }
    }

Couple of interesting things,
  • It uses the fluent API interface.
  • If you want to extend a class object, simply call the Extends method and pass the parent class to it.

Usage of it is pretty simple too,

class Program
   {
       static void Main(string[] args)
       {
           var dict = new Dictionary<string, object>() { { "Name", "Fahad" }, { "Age", 25 } };
           var personalInfo = new CaseClass(dict);
           dynamic d1 = personalInfo;
           Console.WriteLine(d1.Name);
           Console.WriteLine(d1.Age);

           var work = new CaseClass(new Dictionary<string, object>() { { "Profession", "Software Engineer" } });           
           dynamic d2 = work.Extends(personalInfo);
           Console.WriteLine(d2.Profession);

           Console.ReadKey(true);
       }
   }

This shows the power of C#, (of course you don’t get intelli-sense / static typed values), but then its only for specific use cases, not everyone has to deal being dynamic. There are couple of more features that the Scala case classes provide, the ToString() / GetHashCode() / Equals() overrides that the scala compiler does for you. Anybody interested can simply add some more functionality in the above code.

Disclaimer: This post is just to show the usage of C# in one way as in Scala, It doesn’t completely replicate the functionality that is provided as-is in Scala.

-Fahad

Being Very “Dynamic” – C# 4.0 – I

The world of .NET programming is heading towards a new direction, lots of frameworks, languages, services etc., to choose from. With all the rapid development, C# is also heading towards a new future, being to match the inter-op (or rather co-exist) with its Dynamic siblings (IronPython / IronRuby), it is rather fascinating to bridge the gap between two worlds, where the latter evolved from the previous one.

image

With C# 4.0, we have a new keyword “dynamic”, which offers the following features,

  • Binding with DLR
  • COM – Interop made easy
  • Conversions – between dynamic objects and other types are easy.

There may be scenarios, where constructing a dynamic object is absolutely necessary, Say, if we need to write some object reading from XML or some ATOM feed, we would normally parse the data to some predefined set (a static class). All is good in the world of static typing, and areas where you know exactly how your data (or Business object) would be. For dynamic scenarios, We have dynamic meta-data driven based programming, For instance, we could implement ITypedList, ICustomTypeDescriptor, or any derived version of PropertyDescriptor or any custom interface that defines the logic behind driving the meta-data.

The dynamic introduces a DynamicObject class that acts as an interface between the object store and the interaction between the CLR. You would simply have to inherit from the DynamicObject class and implement methods that would be used on the dynamic instance.

We will check out one simple sample that extends DynamicObject to have an object store,

public class MyDynamicObject : DynamicObject
{
private Dictionary<string, object> members;
public MyDynamicObject()
{
this.members = new Dictionary<string, object>();
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (this.members.ContainsKey(binder.Name))
{
result = this.members[binder.Name];
return true;
}
else
{
return base.TryGetMember(binder, out result);
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (!this.members.ContainsKey(binder.Name))
{
this.members.Add(binder.Name, value);
}
else
{
this.members[binder.Name] = value;
}
return true;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return this.members.Keys;
}
}

To use this we declare a dynamic instance,

dynamic d = new MyDynamicObject();
d.Name = “Hello World”;
Console.WriteLine(“Name : {0}”,d.Name);

With some help from the “reflector”, I was able to get an idea on how the dynamic objects were getting constructed in memory. And, thus came up an idea to write down a helper class that would automatically generate “CallSites” for Get/Set property,

public static class DynamicHelper

{
public static object GetValue(object dyn, string propName)
{
// Warning: this is rather expensive, and should be cached in a real app
var binder = Binder.GetMember(CSharpBinderFlags.None, propName,
dyn.GetType(),
new List<CSharpArgumentInfo> {
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
});
var getterSite = CallSite<Func<CallSite, object, object>>.Create(binder);
return getterSite.Target(getterSite, dyn);
}

public static void SetValue(object dyn, string propName, object value)
{
var binder = Binder.SetMember(CSharpBinderFlags.None, propName, dyn.GetType(), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.LiteralConstant | CSharpArgumentInfoFlags.UseCompileTimeType, null) });
var setterSite = CallSite<Func<CallSite, object, object, object>>.Create(binder);
setterSite.Target.Invoke(setterSite, dyn, value);
}
}

Keeping my fingers crossed, we should probably get the dynamic keyword support for WPF GridDataControl (hopefully with Silverlight too).

Sample codes for the post can be downloaded here.

– Fahad

Tagged