Click here to Skip to main content
15,880,905 members
Articles / Mobile Apps

Using MyXaml on the Compact Framework

Rate me:
Please Sign up or sign in to vote.
4.33/5 (10 votes)
22 Aug 2006CPOL6 min read 63.5K   206   23   7
An article on the application of MyXaml on the Compact Framework.

Contents

  • Introduction
  • Missing functionality
  • RunTimeCompilation
  • Implementation of CreateDelegate
  • ISupportInitialize and Trace
  • TypeDecoder
  • XPath
  • Including user defined events
  • Other changes
  • Test application
  • Conclusion

Introduction

We are involved in research into adaptive user interfaces. These interfaces should be shown on desktop as well as on a PDA. Of course, the appearance on these devices would be totally different. The research focuses on the rules that determine the design decisions. To be able to create a user interface ‘on the fly’, you must have a mechanism to create controls, and also have a textual description of the various controls to be created. For desktop applications, a number of alternatives are available: UIML, XAML, and MyXaml (among others), the last two mentioned are not applicable on the PDA. After studying the possibilities, we decided to use the MyXaml (developed by Marc Clifton). UIML for the Compact Framework came available after we finished that port.

The reasons to choose MyXaml were:

  • MyXaml is not only a parser but actually is a framework in which applications can be developed, including the MVC-pattern, Workflow etc.
  • A designer of the XML files which describes the interface is available.
  • It uses “normal” window-control properties description. This article describes the alteration we made to be able to use the MyXaml on a PDA.

The code in the initial article was for CF 1.0. In this update, the source has been ported to the 2.0 version "the easy way". That means, the actual code is not changed, just imported in a 2.0-project.

Missing functionality

When the code from the MyXaml parser is put in a Smart Device application, a number of missing functionalities were detected:

  • RunTimeCompilation
  • CreateDelegate
  • TypeDecoder
  • ISupportInitialize
  • XPath
  • Trace, and there were minor differences about the number of parameters in the function.

RunTimeCompilation

Because of the absence of the CodeDom namespace, it is not possible to compile code at runtime. Even if this was available, it can be argued that it is not likely to be used on the PDA because of the fact that the processors are not as fast as on the desktop. The implementation of the Codebehind tag is, therefore, adapted to make it possible to include already compiled code.

Example code-behind declaration in the MyXaml file:

XML
<def:CodeBehind>
  <reference assembly='CodeBehind.dll'/>
</def:CodeBehind>

In the parser, the references are found, and the assemblies are imported as follows:

C#
foreach(XmlNode codeBehindNode in (
 (XmlElement)formNode). GetElementsByTagName("def:CodeBehind"))
{
   ArrayList references=GetReferences(codeBehindNode);

   foreach (string a_ref  in references) {
  generatedAssembly = Assembly.LoadFrom(a_ref); 
  if (generatedAssembly != null)
  {
    // if code-behind/inline code exists
    // and we're successful in generating the code
    // then instantiate the all the declared classes.
    // Add them to the class collection for this form.
    Hashtable classList=InstantiateInlineClasses(generatedAssembly);
    foreach(DictionaryEntry entry in classList)
    {
      classCache.Add(entry.Key, entry.Value);
    }
  }
  }
}

Note that the LoadFrom is used instead of the LoadWithPartialName.

Besides this solution, the code-behind can also be used by inserting the code-behind class during initialisation of the form. Before the form is loaded, the class of the code-behind is instantiated and inserted into the parser.

C#
public class Startup
{
  public void Start()
  {
    MyOtherClass c=new MyOtherClass();
    Parser p=new Parser();
    p.AddTarget(c);
    Form form=(Form)p.LoadForm("app.myxaml", 
                    "AppMainForm", this, null);
    Application.Run(form);
  }
}

public class MyOtherClass
{
  public void OnDoubleClick(object sender, EventArs e)
  { 
    // ... event handler
  }
}

More details are described here. In the sample included, this last method is applied.

Implementation of CreateDelegate

In the Compact Framework, the CreateDelegate function is absent, but since a delegate object is present, a workaround can be made. First, create a CreateDelegate class with variables for the event target, the parameters of the event function, and the method info.

C#
public class Createdelegate
{
  object eventtarget;
  MethodInfo mymethod;
  object [] methodparams = new Object[2];

  public void Invoke(object sender, System.EventArgs e)
  {
    methodparams[1] = e; 
    mymethod.Invoke(eventtarget, methodparams);
  }

  public Createdelegate(MethodInfo mi, 
         object eventTarget, object eventObject)
  {  
    eventtarget = eventTarget;
    mymethod = mi;
    methodparams[0] = eventObject;
    methodparams[1] = null;
  }
}

Where in the full framework a CreateDelegate function is called, now a function is called which gets the method to implement and then creates the delegate. By invoking this delegate, the event handler is created and this is the result looked for.

C#
private Delegate SearchDelegate(object eventTarget, 
string methodeName, object eventObject)
{
  Delegate dlg=null;
  try
  {
    MethodInfo implementMethod = eventTarget.GetType().GetMethod(methodeName);
    Createdelegate  mydlg = new Createdelegate(
         implementMethod, eventTarget, eventObject); 
    dlg =  new EventHandler(mydlg.Invoke);;
  }
  catch(Exception e)
  {
    Trace.WriteLine(e.Message+"  "+e.InnerException);
  }
  return dlg;
}

ISupportInitialize and Trace

The ISupportInitialize is also not supported. But implementing this is very simple. The interface has two members (BeginInit and EndInit), and the implementation is:

C#
public interface ISupportInitialize
{
  void BeginInit();
  void EndInit();
}

Trace has no implementation of WriteLine. Because the class cannot be inherited, a new class is made which does implement the WriteLine. Be aware of the fact that the WriteLine writes its output to the console, which is not visible in normal PDA use. A console can be started on the PDA, but because the applications are normally used in “maximized” state, it is not easily visible. The messages can be monitored during development by putting a breakpoint at the WriteLine function.

TypeDecoder

Missing functions from the TypeDescriptor were more work to implement. Actually, it is not completely implemented. In the UIML.net source, an implementation was partly available. This code is adapted, and a conversion for other types (i.e., FormBorderStyle, Color) is included. Still this module is far from complete.

XPath

XPath was the last item not implemented in the Compact Framework. Luckily for us, XPath was mostly used in parts of the code we did not use. The few places where it was used could be replaced by the GetElementsByTagName.

Other changes

In the parser, several other components are present which we did not try to convert. Either because we do not use it (e.g., Datasource) or because it is too much work to implement (e.g., StyledListBox).

Including user defined events

After the initial article, a user wanted to use events which he could define himself. To enable this, you have to implement a function called CreateHandler. This is called from the MyXaml code if the event is not of the standard EventHandler type. In your code, you have to include two parts.

First, you define the event you need in the normal way, and its delegate:

C#
public delegate void WhateverEventHandler(Object sender, 
                     ButtonClickEventArgs e);

public class WhateverEventArgs: EventArgs
{
    public WhateverEventArgs()
    {
    }
}

public class WhateverEventDelegate
{
    Object target;
    MethodInfo mymethod;

    public void Invoke(Object sender, WhateverEventArgs e)
    {
        mymethod.Invoke(target, new Object[] { sender, e });
    }

    public WhateverEventDelegate(MethodInfo mi, Object eventTarget)
    {    
        target = eventTarget;
        mymethod = mi;
    }
}

In this example, I did not change the argument, but that is trivial.

Secondly, you have to link this event by including the CreateHandler function, the event, and the actual raising of the event:

C#
public Delegate CreateHandler(Type type, object target, string method)
{
    Delegate dlg = null;
    MethodInfo implementMethod = target.GetType().GetMethod(method);
    if (implementMethod != null)
    {
        WhateverEventDelegate mydlg = 
           new WhateverEventDelegate(implementMethod, target);
        dlg = new WhateverEventHandler(mydlg.Invoke);  
    }
    return dlg;
}

public event WhateverEventHandler RaiseTheEvent;
protected virtual void OnWhateverEvent(ButtonClickEventArgs e)
{
    RaiseTheEvent(this, e);
}

Test application

To test if the adapted code does work, we adapted the simpleCalc.myxaml file that is an example in the MyXaml source. Essentially, only the dimensions of the controls are changed. It shows that all the features of the full framework can be used (like the Style properties). This image shows the resulting interface on the Pocket PC 2005 emulator available in Visual Studio. The user-defined-events have been used, but for demonstration purposes only.

Conclusion

We started off to be able to build user interfaces for the desktop and the PDA using the same code and the same MyXaml files. This is possible by using two solutions (one for each platform) and using compiler switches. The code became unclear, and also specific maps had to be used for the classes that used a form and for the resulting binaries. Using the same MyXaml file forces the desktop developer into using the small set of functions for the Compact Framework, in particular in the attributes used. So we did not merge the code sources. Of course, that implies that for each revision of the MyXaml, the conversion had to be done. The parser is part of a greater framework, but because it involves dynamic generation of code, which is then compiled, this cannot be used on the Compact Framework. So the framework can only be applied on the desktop. Given the small surface of the PDA and the available processing power, we anticipate only simple interfaces are used on a PDA. Clearly, we did not invent new things. We just combined information available in the various newsgroups and open-source projects. We were able to convert MyXaml to the PDA, and it took only moderate time because of the excellent work Marc did.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) produxi
Netherlands Netherlands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralCreateDelegate question Pin
Gerard Savage18-May-06 6:26
Gerard Savage18-May-06 6:26 
GeneralRe: CreateDelegate question Pin
BertjeBier18-May-06 8:42
BertjeBier18-May-06 8:42 
GeneralTrying to build and run the CF version Pin
fkx14-Nov-04 7:48
fkx14-Nov-04 7:48 
GeneralRe: Trying to build and run the CF version Pin
BertjeBier5-Dec-04 10:08
BertjeBier5-Dec-04 10:08 
GeneralUIML on the Compact Framework Pin
kluyten10-Sep-04 6:47
kluyten10-Sep-04 6:47 
GeneralRe: UIML on the Compact Framework Pin
BertjeBier13-Sep-04 9:46
BertjeBier13-Sep-04 9:46 
GeneralMost Excellent! Pin
Marc Clifton5-Sep-04 11:38
mvaMarc Clifton5-Sep-04 11:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.