为 Microsoft .NET Framework 精简版创建多窗体应用程序框架(转)

适用于:
Microsoft®.NET Framework 精简版 1.0
Microsoft Visual Studio® .NET 2003

摘要:学习如何为基于 .NET Framework 精简版的应用程序创建有效的用户界面引擎。

下载 FormStack.msi(英文)。

简介

在进行绝大多数应用程序设计时,首先要考虑的设计问题之一是如何实现图形用户界面 (GUI) 导航,即如何向用户显示新的信息屏幕。在传统的 PC 环境中,应用程序只为每个信息屏幕创建一个新窗体(或对话框)。

在开发人员使用 Microsoft® eMbedded Visual Basic® (eVB) 之前,这种方法一直很有效。使用 Microsoft® eMbedded Visual Basic® (eVB) 后,如果应用程序中包含很多窗体,则很快会将宝贵的内存资源用尽;如果在所有窗体中都需要使用菜单,则最终不得不复制大段代码以保持行为的一致性。

为解决这一问题,许多 eVB 开发人员选择在单个窗体中使用多个框架。开发人员要使用 Microsoft® .NET Framework 精简版,应再次检查生成有效用户界面 (UI) 引擎(未与使用此引擎的应用程序紧密耦合)的方法。

限制资源的使用

使用现今的计算机,桌面应用程序开发人员几乎无须顾虑内存的使用情况。而智能设备开发人员则不得不考虑这个问题。要尽量减少内存的使用,方法之一是尽可能重复使用类,尤其是 Forms 类。

例如,让我们来看看可以在当地录像带出租商店找到的电影查询应用程序。我们假设此应用程序启动时将显示所有电影的列表。不可否认,这将是一个庞大的列表,而且是一个很糟糕的应用程序设计,但出于演示目的我们假设它是合理的。

现在,如果某位用户选择了一部电影的名称,应用程序将显示另一个窗体,其中显示这部电影的详细信息(包括演员)和另一个类似的推荐电影列表(“如果您喜欢这部电影,那么可能也会喜欢 . . . ”)。

20051221173339820.gif

图 1:屏幕流程图

在流程图中,我们假设用户既可以从新列表中选择电影,仅将有关这部电影的新信息重新填充到当前窗体中;也可以选择演员。如果选择演员,可以立即显示演员的信息,包括合演的明星以及另一个电影列表,这次将显示列出此演员出演的电影列表。

很显然,如果查看的每个窗体都是带有所有关联数据的新窗体实例,则应用程序将很快占用大量内存。而且,Windows CE 设备的处理器性能通常都赶不上台式计算机的性能,使用新数据加载每个窗体将生成一个缓慢、响应迟钝且用户不友好的应用程序。

堆栈和缓存

现在,我们将深入了解另一个对用户有益的功能,即查看上一个窗体,它与浏览器中的“后退”按钮功能类似。这就意味着,应用程序必须“记住”用户的位置。

在某些应用程序中实现此操作比较简单,因为窗体的“目标”和“起始”路径很有限,可通过硬编码来实现。对于我们的应用程序,您可以看到这些窗体显示给用户的顺序几乎是随机的(参见图 1)。

因此,我们现在需要了解基本要求。首先,我们希望尽量减少内存中保留的窗体数;其次,我们希望记录用户查看过的窗体以及查看顺序。事实上,我们可能还希望跟踪在每个窗体中查看的数据,但是完成架构后,它只是一个简单的新增部分,请读者自己练习。

那么,到底什么解决方案能够满足这些要求呢?要尽量减少窗体数,可以使用所谓的缓存。缓存只是一种存储机制,可用于保存已加载窗体的单个副本,并在可用时重复使用缓存的窗体。这就意味着当用户要查看窗体时,应首先检查它是否位于缓存中。如果不在缓存中,则按正常方式加载。但如果不是简单地显示缓存的窗体,而是要在内存中保存一个新副本,则还需要考虑实际创建窗体的时间。

可以使用堆栈跟踪已查看的窗体的历史记录。假设查看的每个屏幕都可以表示为一张卡片,而这些卡片可以插入到堆栈中。用户查看每个屏幕时,可以将卡片插入(压入)堆栈中。也就是说,位于顶部的卡片是最后查看的窗体;要查看历史记录,只需从堆栈中删除(或弹出)卡片即可。使用这种方法,应用程序可以“撤消”由用户执行的任意数量、任何顺序的浏览操作。

设计 FormStack

我们已经了解了需要满足的要求和基本方法,现在让我们看看如何实现它们。首先,让我们仔细考虑完成这项工作需要执行的操作。

我们将需要 FormStack,它可以作为类来实现。它需要一种压入和弹出窗体的机制。还需要一个用于存放实际窗体的缓存和一个堆栈,鉴于前面介绍的资源问题,缓存不应该保存窗体的实际副本,而应该只保存一个标识符。我们将窗体类的类型用做字符串。

加载窗体并非瞬间即可完成,尤其是当窗体包含许多控件时。必须创建窗体的所有控件,通常可能需要为列表和下拉列表提取数据。提取数据后,则需要填充控件。如果在应用程序进程的主线程中执行以上所有操作,则在加载窗体的过程中,用户必须等待很长时间。

为了减少等待时间,需要添加两个功能。首先,应该使用辅助线程提取所有需要的数据;然后,添加一个方法,允许应用程序在缓存中“预先加载”一个窗体。这就使应用程序能够在后台或在空闲时(例如启动画面过程中)加载“重型”窗体。

实现缓存和堆栈时还需要考虑其他一些问题,但是我们先定义所需的核心内容。由 FormStack 类完成的实际操作几乎都会在“压入”或“预先加载”过程中启动,因此,我们先看一下其中的逻辑。

20051221173339297.gif

图 2:执行压入

图 2 显示了“压入”的执行流程图。正如您看到的,我们只检查缓存是否存在,如果不存在,则调用“预先加载”;否则,只显示窗体并将其添加到堆栈中。

20051221173339889.gif

图 3:执行预先加载

尽管预先加载(参见图 3)执行的步骤略多一些,但还是比较直观。首先,必须创建 Form 类。在调用标准 InitializeComponent 方法创建窗体的所有控件之前,启动数据查询线程。

一个重要的步骤是,创建所有控件后,必须等待数据查询线程完成才能填充控件,因此需要处理一些基本的线程同步。

填充控件后,最后一步是将控件添加到缓存中。

StackForm 类

FormStack 的实际代码实现与这些流程图基本相同。首先,我创建了所有窗体必须继承的 StackForm 基类。这样,即使窗体不使用基本架构,也可以确保其存在(例如数据线程和控件填充方法)。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10294527/viewspace-126756/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10294527/viewspace-126756/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值