如何在LightSwitch中向自动完成下拉框添加数据

[原文发表地址]: How to Allow Adding of Data to an Auto-Complete Drop-down Box in LightSwitch

[原文发表时间]: 2011-08-16 14:39

我在上篇博文中向你们展示了如何在Visual Studio LightSwitch创建多栏自动完成框,也向你们展示了如何使用多布局,在自动完成框中编辑数据。在这篇博文中,我要公布另一个商业应用中的常用案例—让用户直接向自动完成框键入新数据行。我们的自动完成框显示的是查找表中的数据,我们希望如果用户没有找到它们需要的选择内容,他们可以自行往表中添加数据。我继续使用上一篇博文中的数据模型,也就是分类中有许多产品。

我现在有一个产品屏幕,可以让我们从自动完成框中选择分类。你可以通过点击分类名称编辑分类。

现在我想实现,用户无需手动打开创建新分类屏幕就能添加新分类。通过屏幕上简单的点击就应该可以。我们可以在顶端条上新加一个按钮,但更好的想法是在自动完成框旁添加按钮。

向屏幕添加命令

你可以在屏幕中许多不同的地方添加命令。其实所有组控件都有所谓的“命令栏”,在那里你可以放置按钮或链接以执行命令。这就能让你在正确的环境中设置命令,靠近需要运行的控件。要添加一个紧挨着自动完成框的命令,你可以打开屏幕设计器中的屏幕,展开目录树中自动完成框节点,选择“命令栏”。然后你就可以添加一个新的按钮。

这样会打开“添加按钮”对话框,让你创建一个函数。你在这个函数中设置代码以执行命令。在这个例子中,我把这个函数命名为添加新分类(AddNewCategory)。

系统默认以按钮形式在自动完成框下面显示。你也可以选择用链接形式显示,只要在控件类型中属性窗口选择“链接”就可以了。我还喜欢在命令显示名后添加一个省略号,来告诉用户会有另一个屏幕打开。

当你运行这个应用程序时,你会看到命令显示如下:

程式化调用新数据屏幕

现在我们要写些代码来执行我们的命令。在屏幕设计器中,在命令上右键,选择“编辑执行代码”。

现在我们要调用我们的创建新分类(CreateNewCategory)屏幕。你可以通过应用对象进入你应用程序中的所有屏幕。

 Private Sub AddNewCategory_Execute()
 ' Write your code here.
 Me.Application.ShowCreateNewCategory() 
End Sub

这会打开我们想要的新数据屏幕,不过,LightSwitch总是在保存新数据屏幕之后默认打开默认编辑屏幕。如果你打开了创建新分类(CreateNewCategory)屏幕,点击设计器顶端的“编写代码”按钮,你就会看到下列代码:

 Private Sub CreateNewCategory_Saved()
 ' Write your code here.
 Me.Close(False)
 Application.Current.ShowDefaultScreen(Me.CategoryProperty)
End Sub

我希望在用户直接向自动完成框添加东西的时候,默认编辑屏幕不会显示。所以我们要做的就是创建一个屏幕参数,这样我们就能选择性地显示默认编辑屏幕了。在创建新分类(CreateNewCategory)屏幕设计器中选择设计器工具栏上的“添加数据项”。添加一个Boolean类型的本地属性,不勾选“是否必须”(Is Required)。将参数命名为“显示默认编辑屏幕”( ShowDefaultEditScreen)。然后点击确定。

这就会往屏幕添加一个属性。然后在属性窗口你要确认勾选了“是否为参数”。

现在下拉“编写代码”按钮,选择CreateNewCaegory_Saved()函数,并写上如下代码:

 Private Sub CreateNewCategory_Saved()
 Me.Close(False)

 'If the parameter was not passed in, or if it is explicitly True, then show the default edit screen
 If Not Me.ShowDefaultEditScreen.HasValue OrElse Me.ShowDefaultEditScreen Then
 Application.Current.ShowDefaultScreen(Me.CategoryProperty)
 End If
End Sub

当我们想要从ProductDetail界面中通过命令来调用这个屏幕时,现在我们只需要给这个ShowCreateNewCategory函数传递一个“False”参数就可以了。

 Private Sub AddNewCategory_Execute()
 ' Write your code here.
 Me.Application.ShowCreateNewCategory(False) 
End Sub

继续并运行,看看你到哪一步了。当你点击“添加新分类…”命令时,创建新分类(CreateNewCategory)屏幕就会显示,让你键入新分类。点击保存,屏幕关闭重新显示产品详情屏幕。要查看新分类,点击自动完成框下方的“刷新”按钮。

自动刷新数据列表

你可能会想怎么样能让自动完成框自动地刷新,而不用用户手动点击“刷新”按钮。你屏幕上的每个数据集都有一个.Refresh()函数,你可以方便地从同一屏幕中调用。在自动完成框(或者modal window picker)中,为了获取这个函数功能你需要自己创建一个查询来取代系统自动生成的那个查询。

不过要从其他屏幕调用刷新,我们需要研究下线程方面的细节。LightSwitch应用总是多线程的,所以应用程序在加载或处理远程数据时总能迅即响应。因为LightSwitch离不开数据处理,所以当你在编写代码时(即时在屏幕中),你在编写处理数据方面的线程代码。要在一个屏幕上调用另一个屏幕上的函数,你要将调用配置到主UI线程上。这听上去很复杂,但实际不算太复杂。

根据您的需要在跨屏幕间执行数据刷新有很多种方法。一种就是用如何跨LightSwitch屏幕交流中描述的技术。这就用到了应用对象中的自定义事件,当特定数据从任何其他屏幕添加到系统时,它就会通知所有的屏幕。但要达成我们的目的,不需要那么复杂。不用应用对象,LightSwitch有ActiveScreens 数据集,它可以提供给你所有打开的屏幕列表。我们可以用这个数据集来检查屏幕类型,然后调用函数来刷新我们要的数据。这就避免了处理事件,使涉及的范围变小了。

所以要实现这个特定刷新,我们要做以下工作:

  1. 在产品详情(ProductDetail)屏幕上设置分类自动完成框,使用自定义查询代替自动查询。
  2. 在产品详情(ProductDetail)屏幕代码处创建一个公共函数,命名为RefreshCategories,以执行分类刷新。
  3. 在数据保存之后,将对RefreshCategories的调用配置到主线程。

如果你还没做这些事,那么你要做的第一件事就是为自动完成框用查询设计器创建一个查询,然后在编辑详情屏幕上使用这个查询。我要创建的查询叫做SortedCategories,通过Category.Name来归类。在分类表上点击右键,选择添加查询,如下定义查询:

现在打开产品详情(ProductDetail)屏幕,再次选择设计器工具栏上的“添加数据项”。这次选择SortedCategories查询。

然后设置分类自动完成框的“选择”属性为SortedCategories。

接下来点击设计器顶端的“编写代码”按钮,创建一个公共函数,命名为RefreshCategories,在SortedProducts查询中调用刷新。

 Public Sub RefreshCategories()
 Me.SortedCategories.Refresh()
End Sub

最后我们要做的就是在创建新分类(CreateNewCategory)屏幕中编写代码来调用这个函数。回忆一下我们在这里检查一个参数,来决定是否显示默认编辑屏幕。我们可以用同样的方法向这个屏幕添加一个新的参数,来选择是否需要刷新,这样这些对参数的检查就变得各自独立了。不过在这个例子中,产品详情(ProductDetail)屏幕是唯一一个发送“False”给参数的,所以我可以给CreateNewCategory_Saved()函数写下列代码:

 Private Sub CreateNewCategory_Saved()
 Me.Close(False)
 'If the parameter was not passed in, or if it is explicitly True then show the default edit screen
 If Not Me.ShowDefaultEditScreen.HasValue OrElse Me.ShowDefaultEditScreen Then
 Application.Current.ShowDefaultScreen(Me.CategoryProperty)
 Else
 'ProductDetail is the only screen sending False. Refresh the Category auto-complete box
 Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke( Sub()
 For Each s In Me.Application.ActiveScreens
 If TypeOf s.Screen Is ProductDetail Then
 DirectCast(s.Screen, ProductDetail).RefreshCategories()
 End If
 Next
 End Sub)
 End If
End Sub

注意如果有多个界面处于活动状态,这个代码会对所有打开的产品详情屏幕调用RefrechCategories。如果对你来说,这个代码看上去太复杂了,你可以简单地点击自动完成框下的刷新按钮。

我希望这能为你创建更好的用户体验商业应用提供帮助。就像你看到的那样,在Visual Studio LightSwitch中排列控件,与界面交互有多种灵活的方式。要查看视频教学请见:

#21 – 我是怎样:向屏幕添加按钮和链接形式的命令的?
#22 – 我是怎样:在单一自动完成下拉框中显示多栏的?

希望你们喜欢!