在数据输入屏幕上筛选有大量数据的查询列表

原文发表地址 Filtering Lookup Lists with Large Amounts of Data on Data Entry Screens

原文发表时间 2011 9-15 3:53 PM

在数据输入屏幕上筛选有大量数据的查询列表

首先我想说,能回来继续写博客真好。真不好意思我离开了几周——从旅行归来后我一直在内部做一些很酷的东西。我收到了许多你们对于文章和视频的建议,非常感谢你们一直以来那么包容我。今天我要向你们展示创建数据输入屏幕时另一个常见(且必要的)技术。

在我之前关于数据驱动查询列表(有时称为“选择列表”)的博文里,我展示了一些格式化,编辑和添加数据的技巧。如未看到这些博文,请参见以下链接:

在这篇博文中我会向你展示一些不同的方法,来帮助用户在数据输入屏幕上从大量查找列表数据中做选择。比如,假设我们产品与分类间有一对多的关系,在输入新产品时我们就要从自动完成框中选择一个分类。LightSwitch会根据我们创建产品的屏幕自动生成这个分类。然后我们就可以为它设置格式,就像我在先前的例子中展示的那样。

image

现在假定我们设定了上百甚至上千种产品的分类,在为我们的客户创建订单时,我们需要从中选择。这就是我将要使用的数据模型——它显示了一个产品要在一个OrderDetail行项目上被选中。OrderDetail有一个父OrderHeader栏,这个父栏又从属于一个父客户栏,就像good ‘ol Northwind那样。

image

在上面的产品屏幕上,只有20个分类,所以在下拉分类表中显示所有的查询列表数据不成问题。但是,对有许多数据的产品表来说这不是最佳的选择——要下拉数据太多,一下子显示会比较困难。这对我们的用户来说也许也不是一个很有成效的选择,无论他们想上下滚动浏览数据,或了解他们寻找的产品名称来使用自动完成框。更好的方案是使用,能支持更多的搜索选项并为数据分页的模态窗口选取器。或通过给出分类下拉栏,筛选用户首先选择的产品列表。我们来详细看看这两种方法。

使用模态窗口选取器

假定我选择了编辑详情屏幕模板来创建一个屏幕以输入OrderDetail记录。根据默认设置,LightSwitch会自动生成一个产品自动完成框。这同样也适用于OrderHeader,因为它也是OrderDetail的父类。在这个屏幕上,我不想让用户来改变OrderHeader,所以我会把它变成一个总结控件。我还会把产品上的自动完成框将变成模态窗口选取器:

image

我还想让产品按照字母排列显示,所以我还创建了一个名为“SortedProducts”的查询,然后在屏幕顶端选择“添加数据项”,然后选择SortedProducts查询:

image

给屏幕添加完查询后,选择目录树中的产品,设置“Choices”属性从“Auto”改为“SortedProducts”。

image

你还可以决定每页显示多少行的数据,只要选择SortedProducts查询,然后在属性窗口设置每页显示项数即可。默认设置是每页45行。

image

现在点击F5运行应用,看看结果。注意当你运行屏幕时,你可以选择Product旁的省略号,调出模型窗口选取器。用户可以搜索并为数据分页。这对用户来说不仅方便了查询,而且对服务器来说也很高效。

image

使用经筛选的自动完成框

另一个技巧就是使用一个自动完成框作为筛选器进入下一个分类。这限制了需要被下拉并显示给用户的选择数量。如果你有级联筛选列表的话,这个技巧会非常有用。第一次的选择筛选了第二个筛选的数据,然后第二个再筛选下一个的数据,以此类推。数据可以来源于同一个表,也可以像我例子中那样来源于不同的表——你要做的就是在屏幕上正确设置查询,这样它们就可以被适当地选择筛选了。

返回上面的OrderDetail屏幕,把产品目录项设回自动完成框控件。然后我们要为屏幕添加一个数据项来跟踪被选分类。我们会用这个分类来决定产品列表上的筛选器,所以用户只会看见被选分类中的产品。再次点击“添加数据项”,这次添加一个名为“SelectedCategory”本地分类类型属性。

image

然后,把SelectedCategory拖到上述产品的目录树上。LightSwitch会自动创建自动完成框控件。

image

如果你还想给分类列表分类,可以参照我们对产品的分类方法,依照个人喜好创建一个查询,为屏幕添加数据项,然后把选择属性从自动设到查询。

现在我们要对根据分类筛选的产品创建一个查询。有两种方法。你可以创建一个新的名为ProductsByCategory的全局查询,如果这个查询只为这个特定的屏幕使用,你可以点击我们之前添加的SortedProduct查询旁边的编辑查询。我们采用的是这种做法。这会打开查询设计器,你可以在屏幕上本地修改查询。点击+Filter按钮,在Category.Id上添加一个参数化的筛选,然后在第二个下拉栏中选择Category.Id,在第四个下拉栏中选择参数,在最后一个下拉中选择“Add New…”来创建一个参数化的询问。你也可以让这个参数可选或者必选。我们将其设为必选,这样用户就必须在产品显示前选择分类了。

image

最后我们要连接参数绑定。回到屏幕,选择刚在SortedProducts查询上创建的Id参数,在属性窗口设置参数绑定到SelectedCategory.Id。完成此项操作后,左边灰色列中会显示绑定。

image

设置查询参数值后,LightSwitch会自动执行查询,你无需编写额外的代码。点击F5看看结果。注意现在产品下拉列表是空的,你必须先选择一个分类,满足SortedProducts查询,然后执行。还有就是如果你做了产品选择,然后改变了分类,选择仍会显示,不会消失。只要记得每次用户改变分类,产品查询都会在服务器上重新执行一遍。

image

除此之外,你还可能想做的是显示产品所属初始分类。当屏幕打开时,选择分类是空白的。这是因为它是和屏幕属性绑定的,而属性不支持数据。不过我们可以在代码中设定SelectedCategory的初始值。回到屏幕设计器,在右上方下拉有“编写代码”按钮,选择InitializeDataWorkspace方法,编写以下代码:

  1: Private Sub OrderDetailDetail_InitializeDataWorkspace(saveChangesTo As List(Of IDataService))
  2: ' Write your code here.
  3: If Me.OrderDetail.Product IsNot Nothing Then
  4:  
  5: Me.SelectedCategory = Me.OrderDetail.Product.Category
  6: End If
  7: End Sub
 

现在你再运行屏幕,就会显示被选分类了。

使用一对多屏幕上的已筛选自动完成框

上面的实例用的是,编辑一个简单的OrderDetail记录简单屏幕——因为是教学,所以我故意做得简单一点。不过在实际顺序输入应用中,你可能会涉及同时在一对多的屏幕上编辑OrderDetail项,还有OrderHeader。比如,详细项会在header下的网格中显示。

。当在可编辑网格或者一对多屏幕中使用大量选择列表编辑时,使用模型窗口选取器还是不错的选择不过在网格行中使用已筛选自动完成框还没有被直接支持。你可以在一对多屏幕上使用,只需为“已选项”设置一系列的控件,使用已筛选框即可。我来演示一下。

假定我们为OrderHeader创建一个编辑详情屏幕,选择添加OrderDetails。它会自动设置一个OrderDetails可编辑网格。

image

把数据网格行中的产品变为模态窗口选取器,这样就行了——你可以编辑行项目,在每行上使用模态窗口选取器。不过为了使用已筛选下拉技术,我们要在网格下面创建一个可编辑详情部分。在目录树上选择“子目录”行布局,点击+Add按钮,选择Order Details——Selected Item。

image

这会在网格下创建一系列域,来编辑已选详情项(还会添加Order Header,不过我们在这里不需要,可以删除)。要将数据网格行设为只读,我只需要选定数据网格并在属性窗口中勾选“使用只读控件”,并移除数据网格命令栏的“添加…”和“编辑…”按钮。我要添加的是“添加新…”按钮,这就是说模型窗口不会在输入项时跳出,我们会在网格下的控件中进行这些操作。你可以在应用运行时做这些改变,这样你就能实时预览布局了。以下是我的屏幕在自定义模式下的外观:

image

我们设置好了一对多的屏幕,剩下的创建已筛选自动完成框的步骤就跟之前没什么差别了,唯一的区别就是让已选分类按每个行项目显示的代码则已被编辑。重述要点:

1. 为产品创建一个为Category.Id接受Id参数的参数化询问。

2. 将此查询添加到屏幕(如果屏幕上没有的话)并在产品自动完成框控件中设置选择属性

3. 为屏幕添加一个分类类型数据项以跟踪已选分类

4. 将其拖至已选项的产品目录树上,在网格下创建一个自动完成框。

5. 在产品查询中设置Id参数,绑定到SelectedCategory.Id

6. 选择性编写代码设置已选分类

7. 运行

处理集合时,唯一的区别在第六步我们编写代码来设置已选分类时。当新详情项在网格中被选时我们需要再重新设置,而非一次设置。在屏幕设计器上选择左边的OrderDetails集合,然后下拉“编写代码”按钮,选择OrderDetails_SelectionChanged。编写以下代码:

  1: Private Sub OrderDetails_SelectionChanged()
  2: If Me.OrderDetails.SelectedItem IsNot Nothing AndAlso
  3: Me.OrderDetails.SelectedItem.Product IsNot Nothing Then
  4:  
  5: Me.SelectedCategory = Me.OrderDetails.SelectedItem.Product.Category
  6: End If
  7: End Sub
 

image

整理

在这篇文章中,我向你们展示了一些可用的技巧,以便在往屏幕上输入数据时能给用户显示大量查询列表数据。模态窗口选择是最简单有效的方案,不过有时我们要指导用户做正确的选择,我们可以用自动完成框和参数化询问来实现。

希望你们喜欢!