Command is a unit of functionality

So for the search driven UI, modules of functionality needs to be separated from UI completely. It should be loosely bound and functionality needs to be searchable. In WPF, this unit of functionality can be a Command. Command is an Object that implements ICommand interface. So I wrote a small sample that helps me understand this better. This sample shows how one can use commands to implement functionality. The way I implemented it also optimizes for the scenario where UI can be changed without any code change and no need for recompilations which can be useful in customization scenarios. This is an extreme case where UI does not have any event handlers but it only uses commands to implement functionality. To be able to support search driven functionality, it does not need to be that way but it proves the point that command can be unit of functionality. This off course is also used where same functionality is exposed through multiple UI. So it fits right with search driven UI where in response to different queries, different controls (tool bar, menu) need to adjust their visualization. Since controls can execute command, it will still work the way it is supposed to. This is a scenario where application needs to build functionality that can create a contact. I have an application that has a UI to show the contact form (First name, last name) and it has separate unit of functionality that it calls from this UI. It has a searchLibrary dll that we will talk later in detail that contains this functionality. It does not need to live in separate binary but I chose to do so that I can keep clear separation.

Application

In this small application there is no code at all. Everything is done through mark up so that markup can be loaded in loose xaml form without having to recompile the EXE. Application Xaml for the app looks like this. Off course it will need lot more work to make it work in real scenario.

<Application x:Class=”CustomUI.App” xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml” StartupUri=”Contact.xaml”> </Application>

UI Page

Contact.xaml mentioned above is a UI page that is responsible for showing the UI that user can interact with. As I said above none of the UI has event handlers and functionality is exposed through databinding to commands.

<Page
    xmlns=”
http://schemas.microsoft.com/winfx/2006/xaml/presentation
    xmlns:x=”
http://schemas.microsoft.com/winfx/2006/xaml
    xmlns:customcommands=”clr-namespace:CommandLibrary;assembly=commandlibrary”
    Title=”Contact”
    >
    <Page.Resources>
        <customcommands:ContactDataElement x:Key=”ContactDataSource”>
            <customcommands:ContactDataElement.Parameters>
                <customcommands:Parameter Name=”FirstName” Value=”Joe”/>
                <customcommands:Parameter Name=”LastName” Value=”Johnson”/>
            </customcommands:ContactDataElement.Parameters>
        </customcommands:ContactDataElement>
    </Page.Resources>

    <Page.DataContext>
        <Binding Source=”{StaticResource ContactDataSource}”/>
    </Page.DataContext>
    <StackPanel>
        <StackPanel Orientation=”Horizontal”>
            <TextBlock Grid.Column=”0″ Grid.Row=”1″ >First Name</TextBlock>
            <TextBox Grid.Column=”1″ Grid.Row=”1″ Text=”{Binding Path=[FirstName]}”></TextBox>
        </StackPanel>
        <StackPanel Orientation=”Horizontal”>
            <TextBlock Grid.Column=”2″ Grid.Row=”1″ >Last Name</TextBlock>
            <TextBox Grid.Column=”3″ Grid.Row=”1″ Text=”{Binding Path=[LastName]}”></TextBox>
        </StackPanel>
        <StackPanel Orientation=”Horizontal”>
            <Button Grid.Column=”2″ Grid.Row=”4″ Command=”{Binding Path=SaveContact}” CommandParameter=”{Binding Path=Parameters}”>Ok</Button>
            <Button Grid.Column=”3″ Grid.Row=”4″>Cancel</Button>
        </StackPanel>
    </StackPanel>
</Page>

Important things to notice here are marked in bold…

  • First bold section is just a syntax so that XAML parser can find the classes declared below in the XAML
  • Second bold section where I describe the instance of the class that I need. This in real world would be dynamically generated. But as you can see, there is a class that encapsulates the logic of contact data. It has bunch of data that it stores as name value pair
  • Third bold section is where I databind Command property of the button to SaveContact property on ContactDataElement. ContactDataElement exposes the unit of functionality of saving a contact through ‘SaveContact’ property. SaveContact property returns a command to save a contact. It also exposes the Parameters property that will be passed in as argument to execute method on ICommand.

ContactDataElement

This is a class that I created so that I can store the parameters and command in one place. This way my UI can data bind to this object and UI can invoke the command. Here are the top things that this class supports.

  • This object supports indexer so that databinding can be done to properties that are stored in array of parameters. E.g. FirstName and its value is stores as a parameter object in the Collections. To be able to databind it, it needs to support syntax of ContactDataElement[“FirstName”], hence the indexer.
  • It has a property that returns a value of type ICommand. This is used to bind to controls command property so that control can call execute that command. ContactDataElement could support more command semantic such as delete contact, create new etc.

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace CommandLibrary
{
    public class ContactDataElement
    {
        private Collection<Parameter> _parameters;
        private SaveContactCommand _savecontactcommand;

        public ContactDataElement()
        {
            _savecontactcommand = new SaveContactCommand();
            _parameters = new Collection<Parameter>();
        }
      
        public Collection<Parameter> Parameters
        {
            get { return _parameters; }
            set { _parameters = value;}
        }

        public ICommand SaveContact
        {
            get { return _savecontactcommand; }
        }

        public object this[string name]
        {
            get
            {
                Parameter namevalue = null;
                foreach (Parameter p in _parameters)
                {
                    if (p.Name.Equals(name))
                        namevalue = p;
                }
                return namevalue.Value;

            }
            set
            {
                Parameter namevalue = null;
                foreach (Parameter p in _parameters)
                {
                    if (p.Name.Equals(name))
                        namevalue = p;
                }
                namevalue.Value = value as string;

            }
        }
    }
}

SaveContact Command

This is a object that implements ICommand. It knows how to save a contact. Here are the two important things about this class.

  • Execute method encapsulates the functionality that needs to be exposed. In the example, I just show a message box in the execute call but imagine talking to database, webservice or file IO api to be able to save the contact.
  • Parameters Property: This is used to pass the data to execute method.

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;
using System.Windows;
using System.Windows.Data;
using System.Collections.ObjectModel;

namespace CommandLibrary
{

    public class SaveContactCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;
        public delegate void CanExecuteChangedHandler(object sender, EventArgs e);

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            string data = null ;
            Collection<Parameter> parameters = parameter  as Collection<Parameter>;
            foreach (Parameter p in parameters)
            {
                data += p.Name + “*” + p.Value + “*”;
            }
            MessageBox.Show(“Saving to Store ” + data);
        }

        protected void ExecuteChanged(object sender, EventArgs e)
        {
            CanExecuteChanged(this, e);
        }
    }
}

Here is some extra information that does not pertain to this particular information…

FormPost

One could implement support for Formpost in the similar way. Only that really changes is execute method where you can post to a webserver and an extra property on the data element to store the URL where you are supposed to post back. Here I take the same parameters. Create a string out of it that is seperated using ‘&’. Then I create a webrequest for the URL specified write the string to stream and make a webrequest.

        public void Execute(object parameter)
        {
            Collection<Parameter> parameters = parameter as Collection<Parameter>;
            Console.WriteLine(“Post Collection using WebRequest”);

            WebRequest myHttpWebRequest = WebRequest.Create(_url);
            myHttpWebRequest.Method = “POST”;
            string postData = null;

            foreach (Parameter p in parameters)
            {
                postData += p.Name + “=” + p.Value + “&”;
            }

            ASCIIEncoding encoding = new ASCIIEncoding();
            byte[] byte1 = encoding.GetBytes(postData);
            myHttpWebRequest.ContentType = “application/x-www-form-urlencoded”;
            myHttpWebRequest.ContentLength = byte1.Length;
            Stream newStream = myHttpWebRequest.GetRequestStream();
            newStream.Write(byte1, 0, byte1.Length);
            WebResponse myresponse = myHttpWebRequest.GetResponse();
            Object o = XamlReader.Load(myresponse.GetResponseStream());
            NavigationWindow ns = Application.Current.MainWindow as NavigationWindow;
            ns.Navigate(o);

        }

Other controls

Not all control expose Command properties and not interaction with control can cause command to be executed. E.g. TextBox does not expose a command property and what if I want (for some weird reason) want to execute a command on mouse over on a button or something. I could always implement a custom a control that inherits from TextBox and supports the commanding in the inherited class by implementing ICommandSource. From the customization perspective, this is where this method breaks down. There must be a better way to do this.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: