Sunday, May 27, 2012

WindowsForms Truss databinding


Yesterday I blogged about MVVM for WindowsForms and I mentioned Truss, the databinding library à la WPF that is UI independent. Note I said independent, not agnostic. In fact, it can bind to:
  1. an ordinary property contained in an object that implememts INotifyPropertyChanged
  2. a DependencyProperty of a DependencyObject
  3. an ordinary property of a WindowsForms control
When we say DependencyProperty you know it's WPF (or Silverlight).How come it knows how to bind to a property of a WinForms control?

Truss implements a binding strategy that uses the Microsoft PropertyNameChanged Pattern. Given a property Address, Truss attaches itself to the AddressChanged event. It happens properties of WinForms controls raise this event instead of  the PropertyChanged(<propertyname>) event that is raised by INotifyPropertyChanged properties.

A word about binding expressions

In our example, we have:
  • MainForm - the view with two text boxes: txName and txAddress 
  • MainFormViewModel - the ViewModel that contains a Model property of type MainFormModel
  • MainFormModel - the model with two string properties: Name and Address
The listing included in this post aren't MVVM examples, so I won't discuss the technical MVVM side. For this example, we pass the ViewModel reference to the view on the constructor method. On the form Load handler, we bind the model properties to the text boxes in two different ways:
  • using a simple string path expression
  • using a lambda expression
If you are going to inject your bindings using convention over configuration, you must use the first variation.

    Listing 1 - Single part path
    namespace WinFormsBinding
    {
        public partial class MainForm : Form
        {
            private MainFormViewModel _viewModel;
    
            public MainForm(MainFormViewModel viewModel)
            {
                _viewModel = viewModel;
                InitializeComponent();
            }
    
            private void MainForm_Load(object sender, EventArgs e)
            {
                var bindingManager = new BindingManager();
                bindingManager.Bindings.Add(new Binding(this.txAddress, "Text", _viewModel.Model, "Address"));
                bindingManager.Bindings.Add(new TypedBinding<TextBox, MainFormModel>(
                    this.txName, s => s.Text, _viewModel.Model, t => t.Name));
            }
        }
    }
    

    You might be tempted to refer the root object and use a multipart path.

    Listing 2 - Multi part path
    bindingManager.Bindings.Add(new Binding(this, "txAddress.Text", _viewModel, "Model.Address"));
    bindingManager.Bindings.Add(new TypedBinding<MainForm, MainFormViewModel>(
        this, s => s.txName.Text, _viewModel, t => t.Model.Name));

    Well don't. This doesn't work. I'm not sure whether this should work under Truss. I intend to come back on this subject.

    As a closing subject, on my quest for MVVM for WindowsForms I found another interesting piece of MVVM stuf. Magical.Trevor implements convention over configuration to find a View for a given ViewModel and bind both together. The same pattern is also used to self-bind:
    • Button Click event to methods
    • TextBox Text property to string properties
    Magical.Trevor isn't a port of Caliburn.Micro for WindowsForms. As Mike Minutillo says, it's based on some of the ideas found in Caliburn.Micro.

    Saturday, May 26, 2012

    MVVM for WindowsForms


    Some years ago, I became interest in MVVM for developing WPF (and Silverlight) projects. After much research, I chose Caliburn.Micro: small, simple yet powerfull. I like the convention over configuration approach. In spite of MVVM being accused of making you write more code, Caliburn.Micro's convention over configuration means it has the ability to inject the binding code and makes you write less code. Your view classes have no code behind at all: the .cs file is absent. As Caliburn.Micro injects the InitializeComponent() call you don 't need that file at all. You can't write code behind by mistake if there is no file to do it.

    Another nice feature I found in Caliburn.Micro is the implementation of the Screen Activator pattern. You shoudn't open and close views at your will and catch the "isn't saved" issue sometimes and miss it some other times. The “Screen Activator” Pattern is explained by Jeremy Miller. I won't explain it here but it's important to emphasize that it fits the general view separation pattern (MVC, MVP, MVVM).

    Recently I was asked to develop something in WindowsForms. It started life as usual WindowsForms projects: event handlers, more event handlers and even more event handlers. It  became obvious something was missing: screen activator pattern for starters and while we are at it, MVVM for WinForms.

    I asked Google about it and got no obvious results. I asked two of my techies co-workers if MVVM for WindowsForms was possible. Both gave me the exact same answer: "No way! WindowsForms is missing the rich bindings of WPF and Silverlight (OneTime, OneWay, TwoWay, OnewayToSource) and it is also missing the TypeConverters."

    First things first.

    • Screen Activator Pattern for WindowsForms - you can find it here, ported by jagui
    • Rich Bindings and TypeConverters - Truss by Kent Boogaart, does it in an UI independent way
    • Commands - WPF Application Framework (WAF) has a WafWinFormsAdapter project that takes care of some MVVM stuff namely commands


    Again, can we have MVVM for WinForms?

    Yes we can. We have all the pieces. We just have to glue them together.

    Can we port Caliburn.Micro to WindowsForms?

    Not yet. Several problems have to be solved first. Remove four references from Caliburn.Micro and you'll see what I mean:
    - WindowsBase
    - PresentationCore
    - PresentationFramework
    - System.Windows.Interactivity


    The are four bigs issues identified so far:
    1. Get rid of DependencyObject and DependencyProperty that pops a bit everywhere in CM
    2. Replace FrameworkElement and UIElement by WindowsForms objects
    3. Stick to WAF's implementation of Command or replace EventTrigger
    4. Replace DataContext

    There are also a lot of small issues that I hope can be solved easily. I'll report back.

    Saturday, August 20, 2011

    VS 2010 Setup Project - how to upgrade?


    Setup projects under VS2005 and VS2008 were easy to upgrade:
    1. select the Setup project
    2. go to the Properties tab
    3. update the Setup project Version
    4. accept VS suggestion to change the Product Code
    5. build the Setup project
    This isn't enough under VS2010.
    Is it a bug? In fact no. It happens that VS2010 uses the installer in a smarter way. The MSI generated by VS2010 only replaces changed assemblies. The same principle is used by ClickOnce and it makes upgrades faster.

    The question is: what is a changed assembly? Different update date? Different size? Not at all. Assemblies are different when they have a different File Version. As simple as that.
    I'm not sure ClickOnce uses this criteria to identify different assemblies.

    Upgrading a Setup project under VS2010 is a bit more complicated:
    1. update the File Version of all assemblies that are changed for this upgrade
    2. generate new binaries for these assemblies
    3. select the Setup project
    4. go to the Properties tab
    5. update the Setup project Version
    6. accept VS suggestion to change the Product Code
    7. build the Setup project
    To know more about this subject and understand why you need to do it this way under VS2010, you can read an interesting discussion.

    So what about the SolutionInfo and the Consistent Version Numbers Across All Assemblies technique? It's a way to make sure you don't forget to update the File Version of all assemblies, even if they didn't change. It's a kind'a "fail safe" upgrade. Of course you risk to replace too many assemblies that in fact didn't need to be replaced. The choice is yours.

    Sunday, July 31, 2011

    How "dynamic" made my life easier


    Some coworker said once "Every time you hear dynamic means a load of troubles is coming by". I didn't agree. I know lots of interesting stuff can only be done using Reflection and even Reflection.Emit. Just to give some context, you are talking about Microsoft Framework 4.0 and the new type dynamic type declaration.

    As you know C# is a statically typed language. As you also know, this means you must declare the type of every variable, field or property, before you can use it. The var keyword didn't change that rule a bit. Using var you are implicitly declaring tha variable type. The compiler knows the correct type of  var and the keyword is replaced by the correct type at compile time.

    Let's rephrase: the type of each variable, field or property must be known at compile time. Then Framework 4.0 and _Dynamic Language Runtime_ brought us dynamic. We must change the definition above as the real type dynamic is unknown at compile time. A dynamic type can be any type at all so it's legal to do any operation you like with it. The compiler won't complain about it being incorrect as it doesn't know the real type.

    You can argue that System.Object could do the the trick but you also know the range of operations you can do with System.Object is very narrow and you have to cast it to another type in order to get the same kind of usability, I mean in order to support all operations other types support. No more limitations like that:
    • declare a variable as dynamic
    • your first assignmenet to this variable defines the real type it will have
    • the legal or illegal operations will be evaluated after this assignement
    What's the catch? Incompatibilities that couldn't show on compile time will show at runtime. So if you practice "jerk programming", you will get "a load of troubles" and my coworker's statement will prove correct.

    What do I need dynamic for?
    The classical problem is the "custom properties" issue. You have an business application but every customer wants its own set of extra properties and the requirements of the customer can overcome your worst scenarios/nighmares. You could go the Reflection.Emit way but that's really hard for most programers. Let's try the dynamic way.

    Define you CustomPropery class like this:

    using System;
    
    public class CustomProperty
    {
        #region Private Fields
    
        private string _name = String.Empty;
        private string _type = String.Empty;
        private dynamic _value;
    
        #endregion
    
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    
        public string Type
        {
            get { return _type; }
            set { _type = value; }
        }
    
        public dynamic Value
        {
            get { return _value; }
            set { _value = value; }
        }
    }
    


    Notice dynamic is used both on the field and on the property.
    I suppose you will now read the CustomProperty definitions from some storage be it a database, XML file, it really does't matter.

    Now you need a method that converts the type that you read as a String into a Type.

    private static Type GetDataType(string type)
    {
        Type propType = Type.GetType(type);
        if (propType == null)
            propType = Type.GetType("System." + type);
        if (propType == null)
            propType = Type.GetType("App.CustomProperties." + type);
    
        return propType;
    }
    


    Just to put it all together, after reading the definitions to a prop of PropertyInfo type, you assign the real type like this:

    var customProperty = new CustomProperty();
    customProperty.Name = prop.Name;
    customProperty.Type = prop.PropertyType.Name;
    
    Type targetType = GetDataType(customProperty.Type);
    if (targetType != null)
    {
        if (targetType.IsEnum)
            customProperty.Value = ConvertStringToEnum(targetType, "");
        else if (targetType == typeof (Int16))
            customProperty.Value = (Int16) 0;
        else if (targetType == typeof (Int32))
            customProperty.Value = (Int32) 0;
        else if (targetType == typeof (Int64))
            customProperty.Value = (Int64) 0;
    }
    else
    {
        customProperty.Value = " ";
        customProperty.Value = string.Empty;
    }
    


    After the first assignement juts to define the real Type,  you can now take care of assigning the real value, knowing it will have the correct Type.

    In this example I need the properties for use in a PropertyGrid. In each grid row, I show the customProperty.Name followed by the customProperty.Value. The sample presented here is very limited in scope and isn't really a How To. The point is:
    1. there is no keyword to define the real type of a dynamic variable/field/property
    2. the real type is defined by the first assignement
    3. do this assignment as soon as you know the real type
    4. assign the actual value after the previous assignment

    Sunday, July 10, 2011

    You can't serialize Dictionary


    Too bad:)
    I have to make a class MyDictionary with two field, key and value, both beeing strings. Then maybe I can serialize a List.
    Then again, this guy has a Solution!


    Friday, May 20, 2011

    Caliburn.Micro and CSLA framework


    What's better than one framework? Two frameworks!

    Back in February I merged Csla.Xaml.ViewModel with Caliburn.Micro.Screen class and the result was a new ScreenWithModelBase class added to my version of Caliburn.Micro.

    This Caliburn.Micro extension for CSLA.NET makes life easier for those who want to use both frameworks and makes Caliburn.Micro a very interesting alternative to the BXF framework that is so popular on the CSLA world (as Rocky uses it on all Silverlight project samples).

    Yesterday an old announcement on CSLA.NET forum received some attention and Jonny Bekkum asked me whether he could add this class to CslaContrib project. That was done a while ago.

    Sunday, April 24, 2011

    Technical Note: Silverlight code for CSLA 4



    This note was written for CslaGenFork project.

    Summary
    When using a Silverlight client, your application must always use an application server. Because of Silverligt restrictions, the business objects library DLL must be different on the Silverlight client and on the application server. In this post we will see what are those restrictions, the solutions to the issues they raise and how to use the generated code. In fact this post summarizes what needs to be changed in order to run CSLA code under Silverlight.

    N.B. - CSLA Silverlight changes are numbered and marked in bold.


    I - Silverlight restrictions

    Due to security reasons, there are a lot of things you can't do on Silverlight code. For what CSLA cares, there are three things you can't do under Silverlight:
    1. Access a database server, namely SQL Server
    2. Make synchronous calls to the application server
    3. Use reflection on non-public members of other classes (one class can't use reflection on private members of another class)
    Let's analyse the CSLA solutions for each one of these restrictions.


    II - CSLA solutions

    1. The Silverlight client must receive and send the data through the application server.

    CSLA.NET automatically takes care of routing all DataPortal calls to the application server. If CSLA.NET doesn't find a suitable DataPortal method in the client code, it routes the call to the application server.

    1.1. DataPortal_Create is a special case because most of the times you want it to run locally.
    Regular CSLA uses the attribute [RunLocal] to mark DataPortal methods that must be run on the client (client side DataPortal concept). When DataPortal_Create exists, it's a strong candidate to run client side unless you need to load object default values from the database.
    On Silverlight, DataPortal client side methods accept an extra parameter DataPortal.ProxyModes.LocalOnly that forces the DataPortal code to run locally.

    1.1.1. On the Silverlight client, to run DataPortal_Create locally, there must be a specific asynchronous DataPortal_Create method.
    The Silverlight signature is different from the equivalent method that may exist on non-Silverlight clients.
    The Silverlight signature looks like this:
    public override void DataPortal_Create(Csla.DataPortalClient.LocalProxy.CompletedHandler handler)
    The regular CSLA signature looks like this:
    protected override void DataPortal_Create()

    1.1.2. On the Silverlight client, there must be a specific asynchronous factory method that invokes DataPortal.BeginCreate passing that extra parameter.
    The Silverlight invocation looks like this:
    DataPortal.BeginCreate(callback, DataPortal.ProxyModes.LocalOnly);
    The regular CSLA asynchronous invocation looks like this:
    DataPortal.BeginCreate(callback);

    N.B. - All DataPortal_XYZ methods can run locally. This might be useful in scenarios where the Silverlight client is using REST or SOAP services to interact with the database.

    2. The Silverlight client must invoke the application server asynchronously.
    CslaGenFork can generate synchronous or asynchronous code. When generating Silverlight, asynchronous code is always generated. This includes:

    2.1. Asynchronous LazyLoad for properties (may be synchronous or asynchronous under regular CSLA, but never both at the same time).
    If both options for synchronous and asynchronous code generation are set, under Silverlight the getter code will be asynchronous code and synchronous code for non-Silverlight environments.

    2.2. Asynchronous Factory methods (may be both synchronous and asynchronous under regular CSLA).
    The Silverlight and synchronous factory methods are called asynchronously and they invoke the DataPortal methods asynchronously. CGF generates synchronous and asynchronous code according to the settings (no conditions here).

    N.B. - Business rules that must get data from the application server must also run asynchronously. That's a problem that must be addressed by the rule developer but beyond CslaGenFork concerns.

    3. On the Silverlight client, all usual private or protected member must be public.
    This issue is solved with code like this:
    #if SILVERLIGHT
        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
        public ...
    #else
        private ...
    #endif
    The EditorBrowsable attribute intends to hide the member from InteliSense (and from the developer) as a way not to encourage its use.
    This issue shows on the following cases:

    3.1. public PropertyInfo declaration (private under regular CSLA)

    3.2. public class constructor (private under regular CSLA)

    3.3. public AddObjectAuthorizationRules (protected under regular CSLA)

    3.4. public DataPortal methods (some are private or protected under regular CSLA)


    III - What is generated and how to use it

    As of November 2011, CslaGenFork generates both Encapsulated Implementation and Encapsulated Invoke DataPortal models (according to Using Csla 4 ebooks classification). The usual 2 files are generated: the .Designer file and the extended file.
    The extended file is where CGF puts the commented partial method implementation of the Pseudo Event Handlers. Note that all these methods run server side. If you are regenerating a project, you should put a pair of conditional compilation directives around the whole region:
    #if !SILVERLIGHT
    #endif
    In the .Designer file you will also find a lot of directives just like the above. According to the compilation symbols defined in your project, some parts of the code are ignored. This way you take the same source code and get two different DLLs: one for the Silverlight client and another for the application server. The later can also be used on:
    • WPF client application
    • WPF application server
    • ASP.NET application server
    N.B. - For Windows Forms there are other issues (ListBase versus BindingListBase inheritance) that prevent the use of the same DLL.

    One way to accomplish this goal is to make a copy of all source files and put each copy in a different project: one on a Silverlight Class Library project and another on a Windows Class Library project.

    A more usual approach does the same thing except you don't copy the files but use kind'a shortcuts. Say your main project is the Windows Class Library. Put the files there and build it as usual. On the Silverlight Class Library project, add all folders needed by the project. After that, go to each of the folders and add existing items. Now that's the magic part: navigate to your main project files, select the files and instead of clicking Add, click the small down arrow and click Add As Link.

    Tiago Freitas Leal

    Links:
    CSLA.NET
    CslaGenFork