我如何扩展现有的windows移动应用程序与不同屏幕尺寸的设备工作

本文关键字:屏幕 工作 应用程序 windows 何扩展 扩展 移动 | 更新日期: 2023-09-27 18:16:19

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

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

Helpers有一些共享代码,如DB连接、错误报告、自定义对象等。用户控制有自定义按钮,自定义键盘/numpad等。主程序是包含一个基本表单和几个充当页面的用户控件的大部分代码的地方。根据需要显示/隐藏"页面"。

我想要的是关于如何使这个工作在第二个(肖像)设备,并就此问题,任何其他设备可能会出现在未来的建议。

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

当我尝试这个,但是我无法从助手访问主程序基形式。VS不允许我在主程序的helper中添加引用。我猜这是由于循环引用。是否有一种方法,我可以做到这一点,这样我就可以通过景观/肖像和一个表单名称作为参数,知道什么项目的目标?竖屏版将以完全相同的方式运行,只是显示在更小的屏幕上。

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

我已经尽量使这个问题简短,但如果你需要更多的信息,就问吧。如果您能提供任何帮助,我将不胜感激。

我如何扩展现有的windows移动应用程序与不同屏幕尺寸的设备工作

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

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

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

祝你好运!