如何扩展现有的Windows移动应用程序以使用不同屏幕尺寸的设备

时间:2013-05-31 09:50:44

标签: c# winforms visual-studio-2008 windows-mobile compact-framework

我继承了一个专为触摸屏横向设备设计的现有Windows移动应用程序,但现在我需要扩展它以在较小分辨率的人像设备上工作。解决方案的设置(vs2008)如下:

  • 助手计划
  • 用户控制项目
  • 主程序项目

Helpers有一些共享代码,例如数据库连接,错误报告,自定义对象等。用户控件具有自定义按钮,自定义键盘/小键盘等。主程序是大部分代码具有一个基本形式和多个用户控件的地方充当页面。根据需要显示/隐藏“页面”。

我想要的是关于如何为第二个(肖像)设备进行此项工作的建议,以及将来可能出现的任何其他设备。

我最初的想法是将所有可以共享的业务逻辑从主程序移动到帮助程序,然后为较小的屏幕添加一个主程序(纵向)项目,重新设计的表单和用户控件(页面)。这样,景观和肖像项目可以独立部署。

当我尝试这个时,我无法从帮助者访问主程序基础表单。 VS不允许我为主程序添加对辅助程序的引用。我猜这是由于循环引用。有没有办法可以做到这一点,以便我可以传递横向/纵向和表单名称作为参数,以了解要定位的项目?肖像版本将以完全相同的方式运行,但只是在较小的屏幕上显示。

另一个想法是在检测到较小的屏幕时动态调整表单和用户控件,但这看起来很长并且笨重。我不认为使用锚定和对接是一种选择,因为仅仅显示较小版本的横向形式会破坏肖像设备的可用性。

我试图让这个问题尽可能短,但如果您需要更多信息,请询问。我们非常感谢您提供的任何帮助。

1 个答案:

答案 0 :(得分:0)

答案很大程度上取决于原始开发人员是否在他的表单中隐藏了许多业务逻辑。它们中的逻辑越多,你就越需要付出努力来解决这个问题。

就个人而言,我经常编写代码我的业务逻辑是单独的控制器类,它们引用了具有所需属性和事件的接口(而不是表单或全屏UserControl)。然后在完全独立的项目中(每个设备布局一个)我创建我的屏幕并实现UI界面。此appraoch允许您非常轻松地添加设备。

如果表单中有大量逻辑,则另一个版本是将所有表单转换为基类,以便所有代码甚至事件处理程序驻留在其中。通过将子控件标记为受保护或让基类提供访问它们的虚拟方法,使控件可用于子类。然后在每个特定于设备的UI项目中,您从基本表单继承。

在这两种方法中,您的卫星UI项目都会引用具有基类的项目。你打破了循环引用,并通过人们现在称之为控制反转的概念来实现你想要的UI的运行时加载,但它实际上只是动态加载你的类型。就个人而言,我一直在使用一个简单的配置文件和一个简单的实用程序类,它很好用。这是我的装载机类。在查看此内容时,您还可以使用泛型来删除derivesFrom参数并避免强制转换,但这会让您开始:

public static class ObjectLoader
{
//----------------------------------------------------------------------
// public static methods
//----------------------------------------------------------------------

public static object LoadFromAssembly(
    string srcAssembly,
    string typeName,
    Type derivesFrom)
{
    return LoadFromAssembly(srcAssembly, typeName, derivesFrom, true);
}

public static object LoadFromAssembly(
    string srcAssembly,
    string typeName,
    Type derivesFrom, 
    bool throwOnLoadError)
{

    if (srcAssembly == null)
        throw new ArgumentNullException("srcAssembly");
    else if (srcAssembly.Length == 0)
        throw new ArgumentException("Value may not be empty.", "srcAssembly");
    else if (typeName == null)
        throw new ArgumentNullException("typeName");
    else if (typeName.Length == 0)
        throw new ArgumentException("Value may not be empty.", "typeName");
    else if (derivesFrom == null)
        throw new ArgumentNullException("derivesFrom");

    object retVal = null;

    try
    {
        string srcAssemblyPath = Path.Combine(AppDir, srcAssembly);
        Assembly asm = Assembly.LoadFrom(srcAssemblyPath);
        object obj = asm.CreateInstance(typeName);

        if (obj != null && derivesFrom.IsAssignableFrom(obj.GetType()))
        {
            retVal = obj;
        }
        else if (obj != null) // wrong object, cleanup as needed
        {
            if (obj is IDisposable)
                ((IDisposable)obj).Dispose();
        }
    }
    catch (Exception ex)
    {
        if (throwOnLoadError)
            throw;
        // otherwise null is returned...
    }

    return retVal;
}

//----------------------------------------------------------------------
// private static methods
//----------------------------------------------------------------------

private static string AppDir
{
    get
    {

        string appFullPath = Assembly.GetExecutingAssembly().GetName().CodeBase;
        return Path.GetDirectoryName(appFullPath);
    }
}

}
祝你好运!