1

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

  • 帮手项目
  • 用户控制项目
  • 主程序项目

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

我想要的是关于如何使这项工作适用于第二个(纵向)设备以及未来可能出现的任何其他设备的建议。

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

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

另一个想法是在检测到较小的屏幕时动态调整表单和用户控件的大小,但这似乎冗长而笨重。我不认为使用锚定和对接是一种选择,因为简单地显示较小版本的横向形式会破坏纵向设备的可用性。

我试图让这个问题尽可能简短,但如果您需要更多信息,请询问。您可以提供的任何帮助将不胜感激。

4

1 回答 1

0

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

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

如果表单中有大量逻辑,则另一个版本是将所有表单转换为基类,以便所有代码甚至事件处理程序都驻留在那里。通过将控件标记为受保护或让基类提供访问它们的虚拟方法,使您的控件可用于子类。然后在每个特定于设备的 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);
    }
}

}

祝你好运!

于 2013-05-31T13:06:01.337 回答