Visual Studio LightSwitch

借助 Visual Studio Lightswitch 轻松进行高级编程

Beth Massi

下载代码示例

Visual Studio LightSwitch 是 Visual Studio 系列中的新产品,旨在帮助开发人员针对桌面和云快速创建以数据为中心的业务应用程序。 LightSwitch 是一种简化了开发过程的可扩展开发环境,因为它使您可以专注于业务逻辑,而它负责处理其余大量工作。 LightSwitch 非常适合需要快速 执行的小型业务或部门高效率应用程序。

在 LightSwitch 中可以轻松快速地启动和运行,因此您可以专注于对业务至关重要的功能。 您不必编写代码使 LightSwitch 应用程序启动运行,不过,您很快会认识到,业务规则、屏幕工作流和其他特定于业务要求的用户生产功能都需要代码。 此外,您还可以从 Visual Studio 库下载并安装 LightSwitch 扩展,这些扩展可向您的应用程序添加非现成可用的功能。 您甚至可以使用 Visual Studio 专业版或更高版本自己创建扩展。 社区很可能创建一些有趣的 LightSwitch 扩展!

本文旨在帮助使用 LightSwitch 的专业开发人员加快以数据为中心的典型业务应用程序的开发,或增强最初由其他人构建的 LightSwitch 应用程序。 我将演练 LightSwitch 开发人员可使用的一些更加高级的开发和自定义方法。 我会向您演示如何使用 LightSwitch API、创建自定义屏幕布局、使用高级查询处理、编写复杂业务规则以及使用和创建 LightSwitch 扩展。 您会发现,即使是 LightSwitch 业务应用程序的更高级功能的编程也得到了极大简化,因为 LightSwitch 可为您处理所有的基本功能。 您可以从 code.msdn.microsoft.com/Contoso-Construction-9f944948 下载我将讨论的示例应用程序。

如果您不熟悉如何使用 LightSwitch 创建基本应用程序,建议您看看 LightSwitch 开发人员中心(msdn.com/lightswitch)提供的一些资源。

结构概述

在深入讨论高级 LightSwitch 开发之前,请务必先了解一下 LightSwitch 应用程序的体系结构。 LightSwitch 应用程序基于 Silverlight 和坚实的 .NET 应用程序框架,使用众所周知的模式和最佳做法(如 n 层应用程序分层和 Model-View-ViewModel (MVVM))以及实体框架和 WCF RIA 服务等技术(请参见图 1)。 LightSwitch 团队确保不创造新的核心技术(如新的数据访问或 UI 层);而是围绕这些基于 Microsoft .NET Framework 的现有技术(许多开发人员当前已采用这些技术作为构建基础)创建应用程序框架和开发环境。

LightSwitch Application Architecture

图 1 LightSwitch 应用程序体系结构

此体系结构意味着 LightSwitch 应用程序可以部署为桌面应用程序,同时能够与硬件设备(如扫描仪或条码读卡器)及其他应用程序(如 Microsoft Word 和 Excel)集成;如果需要扩展应用范围,也可以部署为基于浏览器的应用程序。 您还可以通过各种方式(包括使用 Windows Azure)承载 LightSwitch 应用程序。

LightSwitch 的工作都是关于数据和屏幕的处理。 屏幕中的数据通过数据工作区进行管理,数据工作区负责通过查询从中间层中的数据服务提取实体、跟踪变更并通过保存管道将更新发送回中间层数据服务。 在您执行保存命令时,它会使用一个变更集调用数据服务,该服务在一个针对数据源的更新事务中运行。 可以在 LightSwitch 中使用多个数据源(甚至可跨数据源关联实体)。 加入 LightSwitch 应用程序中的每个数据源都有自己的数据工作区。 可以从数据工作区访问针对数据源的所有查询和更新操作。 实体本身也公开底层详细信息,如其实体状态、原始值和当前值。

Visual Studio LightSwitch 是自成一体的 Visual Studio 版本。 它的整个开发环境简化为专注构建 LightSwitch 应用程序。 即使只安装了 LightSwitch 版本,开发人员也可以访问所有 LightSwitch API、Silverlight 和 .NET 框架、自定义屏幕布局和屏幕工作流、复杂验证、保存管道和访问控制挂钩。 您可以编写复杂和复合的 LINQ 查询并使用 COM 互操作,也可以访问客户端和服务器项目代码。

但是,如果您已安装了 Visual Studio 专业版或更高版本,则 LightSwitch 会集成到这些版本中,LightSwitch 应用程序将和其他项目模板一样显示在“新建项目”对话框中。 此外,您还可以为 LightSwitch 创建自定义控件和扩展。

自定义和扩展点

LightSwitch 允许进行各种自定义,从简单代码自定义到创作完备的扩展并将这些扩展分发给其他 LightSwitch 开发人员。

有许多内置挂钩可用于在 LightSwitch 中为实体、查询和屏幕编写代码。 在每个设计器顶部,您都会看到一个“Write Code”(编写代码)下拉按钮,该按钮显示可用的方法挂钩。 通过这种方式可以编写验证和安全规则,可以访问保存管道和查询处理。 您编写的代码有些在服务器上运行,有些在客户端上运行,还有一些同时在服务器和客户端上运行。 通常 LightSwitch 开发人员无需了解其代码的运行位置;LightSwitch 会负责处理所有这些工作。 但是,如果您要提供其他功能,需要编写客户端或服务器上的特定代码,则需要稍微了解一下 LightSwitch 解决方案的结构。

在解决方案资源管理器中查看 LightSwitch 应用程序时,默认情况下处于“逻辑视图”中。但是,如果选择“File View”(文件视图),则可以查看实际的项目和文件结构,如图 2 所示。

Flip to File View to See the Physical Structure

图 2 切换到“File View”(文件视图)查看物理结构

在“File View”(文件视图)中,可以看到“Client”(客户端)和“Server”(服务器)项目,在这些项目之下,可看到 UserCode 文件夹,通过 LightSwitch 开发环境编写的所有代码实际上都放置在该文件夹中。 您可以在此处添加自己的代码文件和类,然后从 LightSwitch 代码进行调用。 不过请注意,客户端在 Silverlight 框架下运行,而服务器在完整的 .NET Framework 4 下运行。 我稍后会演示几个示例。

下一个自定义级别是创作自定义控件和自定义数据源,然后直接在 LightSwitch 项目中使用。 例如,您可以选择创建自己的特殊 Silverlight 控件来提供某些特定功能,然后在 LightSwitch 屏幕上使用该控件。 如果您有 Visual Studio 专业版或更高版本,则可以访问 Silverlight 类库项目模板,可以直接构建自己的控件库,然后在 LightSwitch 中使用。 您还可以创建 WCF RIA 服务,以连接到不是在 LightSwitch 中现成支持的数据源。 但是,若要使这些自定义控件和数据源对仅安装了 Visual Studio LightSwitch 版本的人员可用,需将它们打包为 LightSwitch 扩展。

LightSwitch 中有六个扩展点:

  1. 自定义控件 控件扩展由一个或多个 Silverlight 控件组成,这些控件可以绑定到单个标量值或数据集合。 它还可以将其他控件组合在一起。 控件扩展可以是单个控件;例如,一个星级评定控件或量表,甚至是地图控件。 它也可以是一组控件;例如,发货信息。
  2. 屏幕模板 在创建屏幕时,会为您提供模板列表。 屏幕模板扩展用于创建可以添加到该列表中的新模板。 这样,自定义屏幕可以为所含控件指定布局。
  3. 业务类型 业务类型是 LightSwitch 独有的;通过业务类型,可以为实体属性提供内置的验证和格式设置。 在构建此类型的扩展时,需要为类型定义编辑器控件和格式设置以及验证。 例如,“Phone Number”(电话号码)和“Email Address”(电子邮件地址)是 LightSwitch 中的内置业务类型,可以通过属性窗口以声明方式进行配置。 您可以创建带特定验证和格式设置的“Social Security Number”(社会保险号码)或“Packaging SKU”(包装 SKU)业务类型。
  4. Shell Shell 提供应用程序的外观(即“皮肤”)。它还可以提供导航、命令和屏幕。 如何使用 Shell 呈现(或不呈现)这些内容完全取决于您。
  5. 主题 主题为 LightSwitch 应用程序提供调色板。 您在主题中指定的字形和画笔颜色应用于内置 Shell 或您自己构建的自定义 Shell。
  6. 自定义数据源 所有应用程序都需要某种数据源。 LightSwitch 可以连接到数据库、SharePoint 列表和 WCF RIA 服务。 借助此扩展类型,可以使用 WCF RIA 服务连接到外部数据源。

若要构建扩展,您需要 Visual Studio 专业版或更高版本、Visual Studio SDK 和 LightSwitch 扩展性工具包。 扩展和任何其他 Visual Studio 扩展一样通过 VSIX 包进行分发,并部署到 Visual Studio 库。 然后可以使用扩展管理器(也包含在 Visual Studio LightSwitch 中)安装这些扩展。

现在,了解了 LightSwitch 应用程序中的体系结构、解决方案结构和扩展性范围,我们来深入讨论 Contoso Construction 示例应用程序的一些高级功能。 我构建了整个应用程序,没有使用任何特定自定义控件或数据源自定义项,因此它仅需要 Visual Studio LightSwitch。 但是,我确实安装并使用了公开提供的扩展来增强应用程序,我稍后将演练这些扩展的工作原理。

Contoso Construction 应用程序

在您登录到 Contoso Construction 应用程序时,首先呈现的是定制主屏幕,该屏幕显示常见任务、您的当天约会和当前项目,如图 3 所示。 该应用程序跟踪客户及其建设项目以及项目所用的材料。 它还允许用户管理为每个项目拍摄的照片,安排员工与客户之间的约会。

The Contoso Construction Application Home Screen
(单击进行缩放)

图 3 Contoso Construction 应用程序主屏幕

选择某个项目后,“Project Details”(项目详细信息)屏幕会打开,其中显示一个选项卡控件及其相关子级、项目的材料和图片。 如果指定实体的某个属性属于内置类型 Image(附带图片编辑器并进行显示),则自动使用 LightSwitch 将图片保存到数据库中。

“Project Details”(项目详细信息)屏幕还在功能区中包含一个按钮,用于生成项目状态报告。 它使用 COM 自动打开 Microsoft Word,将项目和材料列表发送给文档。 应用程序的其他功能包括服务器上用于将约会发送给客户和员工的电子邮件集成、审计追踪、包含聚合查询的报告以及自定义查询生成器。 LightSwitch 已具有用于将网格中的数据导出到 Excel 的内置支持。 Contoso Construction 应用程序还具有导入功能,该功能使用户可以将材料数据从电子表格直接上载到屏幕中。 我们来演练一下应用程序的一些更高级部分,以了解如何构建这些部分。

复杂屏幕布局

在 LightSwitch 中构建屏幕时,内容树中的每个控件都必须绑定到数据项。 数据项可以是实体上的字段、实体集合或添加到 ViewModel 的任何其他数据项。 屏幕模板可帮助指导您为特定类型的屏幕(搜索屏幕、详细信息屏幕、新数据屏幕或任何其他类型的屏幕)设置布局和所有数据绑定。 某些屏幕使用单个实体,另一些屏幕使用实体集合。 “Search Screen”(搜索屏幕)、“Editable Grid Screen”(可编辑网格屏幕)以及“List and Details Screen”(列表和详细信息屏幕)模板处理从您可以定义的查询返回的实体集合。 “Edit Details Screen”(编辑详细信息屏幕)处理特定实体,并将参数传入作为要检索的实体的唯一 ID 的查询。

这些模板只是进一步自定义的起点。 事实上,可以选择处理实体集合的屏幕模板,但不为屏幕选择任何数据。 例如,在“Add New Screen”(添加新屏幕)对话框中,可以选择“Search Screen”(搜索屏幕),然后立即单击“OK”(确定)。 这会创建空白“画布”,使您可以从头开始进行。 或者,在选择模板时,可以选择要呈现的基本屏幕数据,然后根据需要将更多数据项添加到屏幕。

数据项可以是基本属性(如字符串或整数);可以是从屏幕代码或按钮调用的方法;也可以是源自查询的实体。 若要手动将数据项添加到屏幕,请单击屏幕设计器顶部的“Add Data Item”(添加数据项)按钮。 然后可以指定数据项的名称和类型。 主屏幕是所有这些类型的数据项的组合,如图 4 所示。

Data Items and the Content Tree in Screen Designer
(单击进行缩放)

图 4 屏幕设计器中的数据项和内容树

对树中的内容进行布局时,可以非常灵活地使用屏幕。 在添加所有数据项之后,若要进行布局更改,较为简单的方法通常是只需运行应用程序(按 F5),打开屏幕,然后单击应用程序右上角的“Design Screen”(设计屏幕)。 这时可以进行布局更改,并实时查看更新。 可以使用分组控件(如表格布局以及行和列布局)来微调应显示控件的确切位置和方式。 然后可以在“Properties”(属性)窗口中调整大小属性以指定确切大小。 除了屏幕命令栏(在横跨应用程序顶部的功能区中显示)之外,还可以为任何控件指定命令栏。 这样,您可以将按钮或超链接放置在树中任何项之下。 在图 4 中,可以看到名为“Search Projects”(搜索项目)的静态文本属性的命令栏将其“Control Type”(控件类型)设置为“Link”(链接),它在运行时会在文本下显示为左对齐(图 3)。

主屏幕显示许多静态文本和图像。 向屏幕上的按钮添加图像就像在“Properties”(属性)窗口中进行设置一样简单。 但是,如果要直接在屏幕上显示图像或静态文本,则需要执行一些操作。 可通过“Add Data Item”(添加数据项)对话框将静态图像和文本作为本地属性添加到屏幕,然后在内容树中对其进行布局。 因为静态属性不是源自数据实体,所以需要在显示屏幕之前设置属性值。 可在屏幕的 InitializeDataWorkspace 方法中执行此操作,该方法在执行任何查询之前运行。 例如,若要设置一个图像和一个文本静态属性,可编写类似于下面这样的代码:

Private Sub Home_InitializeDataWorkspace(saveChangesTo As List(Of IDataService))
            
  ' Initialize text properties
  Text_Title = "Contoso Construction Project Manager"
   
  ' Initialize image properties
  Image_Logo = MyImageHelper.GetImageByName("logo.png") 
  
End Sub

若要加载一个静态图像,可切换到“File View”(文件视图)并将其放置在客户端项目的 \Resources 文件夹中,然后将生成操作设置为“Embedded Resource”(嵌入的资源)。这时,需要编写一些代码来加载该图像。 Contoso Construction 示例应用程序在很多屏幕中使用静态图像,因此我创建了一个名为 MyImageHelper 的帮助程序类,该类可以在客户端代码中的任何位置使用。 同时在“File View”(文件视图)中,右键单击客户端项目中的 \UserCode 文件夹,然后选择“Add”(添加)|“Class”(类)。 将其命名为 MyImageHelper,并创建加载图像的静态(共享)方法,如图 5 所示。

图 5 MyImageHelper 类

''' <summary>
''' This class makes it easy to load images from the client project.
'''
</summary>
''' <remarks></remarks>
Public Class MyImageHelper
  Public Shared Function GetImageByName(fileName As String) As Byte()
    Dim assembly As Reflection.Assembly = 
      Reflection.Assembly.GetExecutingAssembly()
    Dim stream As Stream = assembly.GetManifestResourceStream(fileName)
    Return GetStreamAsByteArray(stream)
  End Function

  Private Shared Function GetStreamAsByteArray(
                          ByVal stream As System.IO.Stream) As Byte()
    If stream IsNot Nothing Then
      Dim streamLength As Integer = Convert.ToInt32(stream.Length)
      Dim fileData(streamLength - 1) As Byte
      stream.Read(fileData, 0, streamLength)
      stream.Close()
      Return fileData
    Else
      Return Nothing
    End If
  End Function
End Class

可以通过这种方式向客户端添加任何自定义代码。 例如,Contoso Construction 示例应用程序还具有用于通过 COM 将建设项目数据导出到 Word 的帮助程序类。 关键是您可以非常灵活地将自己的自定义代码和类添加到 LightSwitch。

使用保存管道

您也可以通过相同方式向服务器项目添加自己的代码。 在示例中,有一个约会屏幕,用户使用该屏幕可以设置客户与员工之间的约会。 如果客户和员工有电子邮件地址,则在将约会实体插入到数据源中时,会将电子邮件约会 (iCal) 发送给双方。 保存管道公开您可以用于编写业务规则、调用其他服务或启动工作流的许多方法,包括用于每个实体的 Inserted/Inserting、Updated/Updating 和 Deleted/Deleting 方法。

用于通过 SMTP 电子邮件发送约会的帮助程序类位于服务器项目的 \UserCode 文件夹中,名为 SMTPMailHelper。 当在系统中更新或删除约会时,应用程序也会发送更新和取消。 若要访问这些保存管道方法,请在设计器中选择实体,然后选择“Write Code”(编写代码)下拉按钮。 悬停在方法上时,工具提示会告知您代码是运行在客户端、服务器还是两者上。 对于约会实体,需要将代码注入服务器端方法(如图 6 所示),以便跟踪和发送新的、更新的和取消的约会电子邮件。

图 6 用于跟踪和发送约会电子邮件的服务器端方法

Private Sub Appointments_Inserting(ByVal entity As Appointment)
  'Used to track any iCalender appointment requests
  entity.MsgID = Guid.NewGuid.ToString()
  entity.MsgSequence = 0
End Sub

Private Sub Appointments_Updating(ByVal entity As Appointment)
  'Update the sequence anytime the appointment is updated
   entity.MsgSequence += 1
End Sub

Private Sub Appointments_Inserted(ByVal entity As Appointment)
  'Send an email notification when an appointment is inserted into the system
  Dim isCanceled = False
  SMTPMailHelper.SendAppointment(entity.Employee.Email,
                                 entity.Customer.Email,
                                 entity.Subject,
                                 entity.Notes,
                                 entity.Location,
                                 entity.StartTime,
                                 entity.EndTime,
                                 entity.MsgID,
                                 entity.MsgSequence,
                                 isCanceled)
End Sub

  Private Sub Appointments_Updated(ByVal entity As Appointment)
    'Send an email update when an appointment is updated. 
    Dim isCanceled = False
    SMTPMailHelper.SendAppointment(entity.Employee.Email,
                                   entity.Customer.Email,
                                   entity.Subject,
                                   entity.Notes,
                                   entity.Location,
                                   entity.StartTime,
                                   entity.EndTime,
                                   entity.MsgID,
                                   entity.MsgSequence,
                                   isCanceled)
           
End Sub

   Private Sub Appointments_Deleting(entity As Appointment)
     'Send an email cancellation when an appointment is deleted.
     Dim isCanceled = True
     SMTPMailHelper.SendAppointment(entity.Employee.Email,
                                    entity.Customer.Email,
                                    entity.Subject,
                                    entity.Notes,
                                    entity.Location,
                                    entity.StartTime,
                                    entity.EndTime,
                                    entity.MsgID,
                                    entity.MsgSequence,
                                    isCanceled)

End Sub

在实现审计追踪时,也会使用保存管道。 审计追踪在业务应用程序中比较常见,用于跟踪系统记录更改以及更改者。 在示例应用程序中,一个名为 EmployeeChange 的表跟踪对 Employee 上字段的更改,如图 7 所示。

An Audit Trail Is a Common Business Application Requirement

图 7 审计追踪是常见业务应用程序要求

若要捕获所更新的 Employee 上的新值和原始值,可以深入了解实体的 Details 属性。 这样可以使用更高级的实体 API。 在 Employees_Updating 方法中,可以动态遍历实体上的所有存储属性并记录其新值和原始值,如图 8 所示。

图 8 深入了解 Employee 实体 Details 属性以创建审计追踪

Private Sub Employees_Updating(entity As Employee)
  'Audit trail that tracks changes to employee records
  Dim change = entity.EmployeeChanges.AddNew()
  change.Employee = entity
  change.Updated = Now()
  change.ChangedBy = Me.Application.User.FullName
  Dim newvals = "New Values:"
  Dim oldvals = "Original Values:"

  For Each prop In entity.Details.Properties.All().
OfType(Of Microsoft.LightSwitch.Details.IEntityStorageProperty)()

    If prop.Name <> "Id" Then
      If Not Object.Equals(prop.Value, prop.OriginalValue) Then
        oldvals += String.Format("{0}{1}: {2}", 
                                 vbCrLf, 
                                 prop.Name, 
                                 prop.OriginalValue)
        newvals += String.Format("{0}{1}: {2}", 
                                 vbCrLf, 
                                 prop.Name, 
                                 prop.Value)
      End If
    End If
  Next
  change.OriginalValues = oldvals
  change.NewValues = newvals
End Sub

有关保存管道、验证框架和实体 API 的详细信息,请参阅 LightSwitch 开发人员中心的“使用代码”部分 (bit.ly/inJ3DE)。

高级查询

因为 LightSwitch 应用程序的工作都是关于数据和屏幕的处理,所以一点也不奇怪,您可以创建查询。 查询设计器提供了一种快速、简单的方式,用于定义筛选、排序和查询参数,以及指定查询是应返回一行还是多行。 还可以使查询以其他查询为基础,如果始终要将某个筛选或排序应用于数据集时,这会非常方便。 您还可以指定必需和可选参数。 但是,查询设计器也有其限制。 幸运的是,您可以单击设计器顶部的“Write Code”(编写代码)按钮(或单击属性窗口中的“Edit Additional Query Code”(编辑其他查询代码)),然后在 PreprocessQuery 方法中编写代码。

在 Contoso Construction 应用程序中,有一个名为 CurrentProjects 的查询,如图 9 所示。 CurrentProjects 查询仅通过设计器定义了一个可选参数;查询的其余部分在代码中进行处理。

The CurrentProjects Query
(单击进行缩放)

图 9 CurrentProjects 查询

请注意,此查询仅定义一个可选参数,未指定筛选或排序。 我们需要检查是否提供了该参数,如果提供,则计算其值以确定是否应用筛选。 向 PreprocessQuery 方法传递您在设计器中定义的所有参数以及查询本身。 这意味着,您可以在设计器中定义筛选和排序,然后通过编写 LINQ 代码添加到查询,以进一步对其进行筛选或排序。 不过请注意,您始终需要返回 LightSwitch 需要的实体类型集合;不能返回投影或其他类型。

这样在 PreprocessQuery 方法中,可以编写如图 10 所示的代码。

图 10 在 PreprocessQuery 方法中截获查询

Private Sub CurrentProjects_PreprocessQuery(
  ShowAllProjects As System.Nullable(Of Boolean),
  ByRef query As System.Linq.IQueryable(Of LightSwitchApplication.Project))

  'If ShowAllProjects is False (or Nothing) then just pull up the 
  ' projects that do not have an actual end date specified.
If Not (ShowAllProjects.HasValue) Then ShowAllProjects = False

  If Not (ShowAllProjects) Then
    query = From p In query
            Where p.ActualEndDate Is Nothing
            Select p

  End If
End Sub

现在,基于该查询创建一个屏幕,LightSwitch 会发现存在一个可选参数,然后自动为您创建该屏幕数据项并将其绑定到查询参数。 ShowAllProjects 是布尔值,因此,它会创建一个复选框,当用户单击该框时,查询将自动执行。

我希望您已开始了解 LightSwitch 提供的所有代码挂钩;查询也不例外。 示例应用程序中另一个有趣的查询使用聚合查看超出预算的项目。 此查询未在设计器中指定任何内容;它仅使用代码,因为它需要聚合子数据以计算项目的材料成本:

Private Sub ProjectsOverBudget_PreprocessQuery(
  ByRef query As System.Linq.IQueryable(Of LightSwitchApplication.Project))

  'Return projects where the cost is over the original estimate
  query = From p In query
          Let cost = p.Labor + 
            (Aggregate m In p.ProjectMaterials Into Sum(m.Quantity * m.Price))
          Where cost > p.OriginalEstimate
          Order By p.StartDate
          Select p
End Sub

在示例应用程序中,这两个查询呈现在搜索数据屏幕上,以便用户将结果导出到 Excel,分析数据并创建报告。这些报告会经常使用,因此,对其进行硬编码是有意义的。但是,允许用户定义自己的自定义报告是一种好方式。为此,您可以安装示例库中提供的筛选控件扩展(包含所有源代码),地址为 bit.ly/fYmEnK

使用扩展

LightSwitch 扩展的安装方式与任何其他 Visual Studio 扩展相同。单击 VSIX 文件进行安装,然后重新启动 Visual Studio。打开 LightSwitch 项目属性,可以看到“Extensions”(扩展)选项卡,在该选项卡中可以选择要在项目中使用的扩展,如图 11 所示。

Enabling an Extension on the Extensions Tab of the LightSwitch Project Properties

图 11 在 LightSwitch 项目属性的“Extensions”(扩展)选项卡上启用扩展

若要使用筛选控件扩展,请创建一个查询并添加一个名为 FilterTerm 的字符串参数,然后将下面的代码添加到 PreprocessQuery 方法:

query = LightSwitchFilter.Server.Filter(query, FilterTerm, Me.Application)

接下来,基于该查询添加一个屏幕,并在屏幕设计器中 将“Filter Term”(筛选术语)控件的 控件类型更改为“Advanced Filter Builder”(高级筛选生成器),并将标签位置更改为“None”(无)。在 Contoso Construction 示例应用程序中,查询名为 CustomFilterProjects,屏幕名为 CustomReport。

在运行示例应用程序并打开 Custom Report 屏幕时,会显示筛选生成器控件。 一旦定义了筛选,Go(执行)按钮将针对服务器执行筛选。 筛选是 Silverlight 控件,会生成设计的筛选的 XML 表示形式。 然后以字符串形式传递给查询。 在服务器上,查询代码分析 XML 并生成适当的筛选子句。

另一个很好用的扩展是 Excel Importer 扩展,可以在 bit.ly/e580r3 处获取该扩展及所有源代码。

LightSwitch 已具有用于将网格中的数据导出到 Excel 的内置支持。 Excel Importer 可以通过将 Excel 列映射到实体的属性,从电子表格导入 数据。 此扩展在示例应用程序中的“Materials Catalog”(材料目录)屏幕上使用。 安装并启用该扩展后,创建一个可编辑网格屏幕,然后向屏幕命令栏添加一个按钮。 在命令的 Execute 方法中,只需编写一行代码:

Private Sub ImportFromExcel_Execute()
  LightSwitchUtilities.Client.ImportFromExcel(Me.Materials)
End Sub

可以看到,在 LightSwitch 中安装和使用扩展来提供更多功能是十分简单的。 将自定义项打包为扩展后,可以广泛分发给其他 LightSwitch 开发人员。

构建自己的扩展

若要构建扩展,需要安装带 LightSwitch 的 Visual Studio 专业版 SP1 或更高版本、Visual Studio SDK 和 LightSwitch 扩展性工具包,该工具包可以从 LightSwitch 开发人员中心 (msdn.com/lightswitch) 下载。 这会将 Visual Basic 和 C# 扩展性项目模板添加到“新建项目”对话框中的 LightSwitch 节点之下。

我们为 Contoso Construction 应用程序创建一个简单主题。 首先创建一个新 LightSwitch 扩展库项目;我将它命名为 ContosoThemes。 这样会为扩展设置所有必要的项目。 可以看到与 LightSwitch 应用程序的文件视图有些相似,但是包含一些其他项目,即 LSPKG 和 VSIX 项目。

接下来,右键单击 ContosoThemes.LsPkg 并选择“添加新项”。 在此处会看到支持的 LightSwitch 扩展模板集。 选择 LightSwitch 主题项并为其提供名称(我将它命名为 PurpleTheme)。 将创建新主题的预内置 XAML 文件并在 IDE 中打开。 默认情况下,它具有标准 Shell 主题中的所有画笔和样式。 您可以使用自己喜欢的任何工具为 LightSwitch 在其 Shell 中显示的每个项设置颜色和样式。 在此示例中,我只是通过使用 XAML 编辑器和属性窗口选择颜色,更改了几个颜色,如图 12 所示。

Creating a LightSwitch Theme Extension
(单击进行缩放)

图 12 创建 LightSwitch 主题扩展

准备好测试扩展后,可以单击 F5 启动调试 IDE 实例。 若要测试主题,请在此实例中创建一个新 LightSwitch 项目。 打开 LightSwitch 项目属性,在“Extensions”(扩展)选项卡上启用刚才构建的 ContosoThemes 扩展。 接下来,切换到“General”(常规)选项卡并选择 PurpleTheme。 您需要创建实体和屏幕,以便在操作中查看主题;然后可以在测试项目中按 F5 以查看其外观。

如果对主题感到满意,则在发布模式下构建扩展,这样可以将位于 VSIX 项目的 \bin\Release 文件夹中的 VSIX 包传递给 LightSwitch 开发人员,供其在任何项目中使用。 您也可以将该包上载到 Visual Studio 库以进行广泛分发。 图 13 是 Contoso Construction 应用程序中显示的主题外观。

Applying a Theme Extension to a LightSwitch Application
(单击进行缩放)

图 13 将主题扩展应用于 LightSwitch 应用程序

有关构建 LightSwitch 扩展的详细信息,请参阅 LightSwitch 开发人员中心 (bit.ly/hoMP7P) 的“高级主题”部分。

总结

LightSwitch 极大简化了以数据为中心的业务应用程序的开发,因为它可为您处理所有的基本功能。 它使您可以专注于用户高效完成工作所需的业务逻辑和其他自定义功能。 对于 LightSwitch 开发人员以及希望为社区构建 LightSwitch 扩展的专业开发人员,有许多自定义级别可用。 希望您通过阅读本文,能够了解 LightSwitch 的灵活度和可自定义度。 有关信息、培训、示例、视频、论坛、社区等,请访问位于 msdn.com/lightswitch 的 LightSwitch 开发人员中心。

请尽情体验吧!

Beth Massi 是 Microsoft Visual Studio BizApps 团队的高级项目经理,该团队为 Windows Azure、Office 和 SharePoint 以及 Visual Studio LightSwitch 构建 Visual Studio 工具。Massi 是业务应用程序开发人员的社区带头人,负责为 BizApps 团队生成和管理联机内容和社区交互。她拥有 15 年以上的构建业务应用程序的行业经验,经常在软件开发活动中发表演讲。她活跃在很多开发人员站点上,包括 MSDN 开发人员中心、第 9 频道以及她的博客 (BethMassi.com)。请关注她的 Twitter:twitter.com/BethMassi

衷心感谢以下技术专家对本文的审阅:Robert Green