65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Compact Framework 上使用 MyXaml

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (10投票s)

2004年9月2日

CPOL

6分钟阅读

viewsIcon

64716

downloadIcon

220

一篇关于在 Compact Framework 上应用 MyXaml 的文章。

目录

  • 引言
  • 缺失的功能
  • 运行时编译
  • CreateDelegate 的实现
  • ISupportInitializeTrace
  • TypeDecoder
  • XPath
  • 包含用户定义的事件
  • 其他更改
  • 测试应用程序
  • 结论

引言

我们正在研究自适应用户界面。这些界面应该同时显示在桌面和 PDA 上。当然,在这些设备上的外观会完全不同。研究侧重于决定设计决策的规则。为了能够“即时”创建用户界面,您必须有一个创建控件的机制,并且还需要有关要创建的各种控件的文本描述。对于桌面应用程序,有许多替代方案:UIML、XAML 和 MyXaml(以及其他),后两者不适用于 PDA。在研究了各种可能性之后,我们决定使用 MyXaml(由 Marc Clifton 开发)。在我们完成对 Compact Framework 的移植后,UIML 才可用。

选择 MyXaml 的原因是

  • MyXaml 不仅仅是一个解析器,实际上它是一个可以开发应用程序的框架,包括 MVC 模式、工作流等。
  • 提供了用于描述界面的 XML 文件的设计器。
  • 它使用“普通”窗口控件属性描述。本文描述了我们为在 PDA 上使用 MyXaml 所做的修改。

原始文章中的代码是针对 CF 1.0 的。在此更新中,源代码已“轻松地”移植到 2.0 版本。这意味着,实际代码未更改,只是导入了一个 2.0 项目。

缺失的功能

将 MyXaml 解析器的代码放入 Smart Device 应用程序时,检测到许多缺失的功能

  • 运行时编译
  • CreateDelegate
  • TypeDecoder
  • ISupportInitialize
  • XPath
  • Trace,并且函数参数的数量存在细微差异。

运行时编译

由于缺少 CodeDom 命名空间,因此无法在运行时编译代码。即使提供了此功能,也可以认为它不太可能在 PDA 上使用,因为其处理器速度不如桌面设备。因此,对 Codebehind 标签的实现进行了调整,使其能够包含已编译的代码。

MyXaml 文件中的示例代码隐藏声明

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

在解析器中,按以下方式查找引用并导入程序集

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);
    }
  }
  }
}

请注意,使用的是 LoadFrom 而不是 LoadWithPartialName

除了此解决方案外,还可以通过在窗体初始化期间插入代码隐藏类来使用代码隐藏。在加载窗体之前,实例化代码隐藏的类并将其插入解析器。

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
  }
}

更多详情请在此处 了解。在随附的示例中,应用了最后一种方法。

CreateDelegate 的实现

在 Compact Framework 中,CreateDelegate 函数缺失,但由于存在委托对象,因此可以找到一种解决方法。首先,创建一个 CreateDelegate 类,其中包含事件目标、事件函数参数和方法信息的变量。

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;
  }
}

在完整框架中调用 CreateDelegate 函数的地方,现在调用一个获取要实现的方法然后创建委托的函数。通过调用此委托,创建了事件处理程序,这就是所需的结果。

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 和 Trace

ISupportInitialize 也不受支持。但实现它非常简单。该接口有两个成员(BeginInitEndInit),实现如下:

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

Trace 没有实现 WriteLine。由于该类不能被继承,因此创建了一个新类,它实现了 WriteLine。请注意,WriteLine 将输出写入控制台,这在正常的 PDA 使用中是不可见的。可以在 PDA 上启动一个控制台,但由于应用程序通常以“最大化”状态运行,因此不容易看到。可以通过在 WriteLine 函数处设置断点来监视消息。

TypeDecoder

TypeDescriptor 中缺失的函数需要更多的工作来实现。实际上,它并未完全实现。在 UIML.net 源代码中,部分实现了此功能。此代码已进行调整,并包含了对其他类型(例如 FormBorderStyleColor)的转换。此模块仍远未完成。

XPath

XPath 是 Compact Framework 中最后一个未实现的项目。幸运的是,XPath 主要用于我们未使用的代码部分。为数不多的使用它的地方可以用 GetElementsByTagName 替换。

其他更改

在解析器中,还有其他几个组件我们没有尝试转换。要么是因为我们不使用它们(例如 Datasource),要么是因为实现起来太麻烦(例如 StyledListBox)。

包含用户定义的事件

在最初的文章之后,一位用户希望使用他可以自行定义的事件。为了实现这一点,您必须实现一个名为 CreateHandler 的函数。当事件不是标准 EventHandler 类型时,MyXaml 代码会调用此函数。在您的代码中,您必须包含两部分。

首先,您以正常方式定义所需的事件及其委托

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;
    }
}

在此示例中,我没有更改参数,但这很简单。

其次,您必须通过包含 CreateHandler 函数、事件和实际引发事件来链接此事件

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);
}

测试应用程序

为了测试修改后的代码是否有效,我们修改了 MyXaml 源文件中的一个示例 simpleCalc.myxaml 文件。本质上,只更改了控件的尺寸。这表明完整框架的所有功能都可以使用(例如样式属性)。此图像显示了 Visual Studio 中 Pocket PC 2005 模拟器上生成的界面。用户定义的事件已使用,但仅用于演示目的。

结论

我们的目标是能够使用相同的代码和相同的 MyXaml 文件为桌面和 PDA 构建用户界面。这可以通过使用两个解决方案(每个平台一个)并使用编译器开关来实现。代码变得不清晰,并且还需要为使用窗体的类和生成的二进制文件使用特定的映射。使用相同的 MyXaml 文件会迫使桌面开发人员使用有限的 Compact Framework 函数集,尤其是在使用的属性方面。因此,我们没有合并代码源。当然,这意味着对于 MyXaml 的每一次修订,都必须进行转换。解析器是更大框架的一部分,但由于它涉及代码的动态生成,然后进行编译,因此无法在 Compact Framework 上使用。所以该框架只能应用于桌面。考虑到 PDA 的小屏幕和可用的处理能力,我们预计 PDA 上只会使用简单的界面。显然,我们没有发明新东西。我们只是结合了各种新闻组和开源项目中提供的信息。我们能够将 MyXaml 移植到 PDA,而且由于 Marc 出色的工作,花费的时间并不长。

© . All rights reserved.