“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情”
创建应用程序
- 直接在正确版本的 Mendix Studio Pro 中创建一个新应用程序。
- 选择空白启动应用程序,因为您将从头开始构建此应用程序。
- 在 Studio Pro 中打开您新创建的应用程序
实体之间的多重关联
在深入了解新理论之前,让我们快速回顾一下在初级教程中的数据模型的关联关系。
在 西门子Mendix 中有三种类型的关联。这些关联允许您在对象之间创建可能的连接。这些连接也称为引用。西门子Mendix 平台具有以下关联类型:
- 一对多 (1 - *)
- 一对一 (1 – 1)
- 多对多 (* - *)
Player 和 Team
我们已经知道了在两个实体之间添加多个关联的可能性,是时候研究如何帮助 Adrian 和 Soccer Squad 应用程序了。
想象一下:一支足球队可以有多名球员(实际上,他们至少需要 11 名球员)。这是一对多关联的完美示例。但是,每支球队只能有一名队长,队长也是一名球员。
您可以通过向 Player 实体添加布尔属性来解决此问题;队长。这将导致每次创建或编辑玩家时都会出现一个输入小部件,用户判断这名队员是不是队长?
也许你认为这个解决方案很好,没关系!但是让我们有一个更好的解决方案,使用 Team 和 Player 实体之间的两个关联。
使用这个领域模型结构,我们可以将许多玩家添加到团队中,并选择其中一名玩家作为队长。第二个协会提供第二个好处:因为它是一对一的协会,你可以立即只有一个队长。这为您节省了必须创建自定义逻辑来执行此操作的工作!
在 Soccer Squad 应用程序中,我们可以在两个实体之间应用多个关联的另一个示例是从 Match 到 Team 的关联。一场比赛由两支球队进行,主队和客队。西门子Mendix 中没有一对二关联。而且,如果您只是使用多对多关联,则无法存储主队是谁。
我们可以使用信息实体模式来解决这个问题。但是,此解决方案将三个数据库表添加到您的数据库中,您需要创建自定义逻辑来强制只能将两个团队添加到比赛中。
另外,这个实体会被称为什么?匹配角色?匹配团队类型?这个解决方案在您开始之前就已经不清楚了。
相反,您可以在 Match 和 Team 实体之间使用两种关联,一种用于 Match_TeamHome,另一种用于 Match_TeamAway。
这会自动强制您每场比赛只能选择两支球队。它只在你的数据库中添加了两个简单的数据库表,而且命名超级清晰!
构建领域模型
开始动手实践我们刚刚学到的知识吧。
看看下面的领域模型。此领域模型告诉您有关 Soccer Squad 应用程序的以下信息:
- 每支球队可以有多名球员。
- 每支球队只能有一名队长。
- 每支球队只能拥有一个体育场(他们的主场)。
- 每场比赛只能在一个体育场内进行
- 每支球队都可以进行多场比赛,无论是作为主队还是作为客队。
- 每场比赛最多可以由两支球队进行,主队和客队。
- 每场比赛可以有多个目标。
- 这些目标可以——通过关联——属于特定的球队,甚至是特定的球员。
-
将MyFirstModule重命名为SoccerSquad。
-
使用上图构建领域模型。
-
将After Create事件处理程序添加到Team实体。此事件处理程序将为创建的每个新Team对象自动创建一个新的Stadium对象。
- 将此事件处理程序连接到名为ACR_Team_CreateStadium的新微流。
- 使用下图构建微流:
创建数据之后的Hander(before event handler)
到目前为止,您只使用了after事件处理程序。before事件处理程序的工作方式略有不同,因为它们总是需要一个布尔返回值。该值告诉应用程序是继续该事件还是中止它。
您可以在将对象提交到数据库之前使用 before 事件处理程序来触发验证过程。验证的结果(对象是否有效,是真还是假)将允许事件继续或中止它。
现在您已经在创建Team后自动创建了 Stadium对象。您还可以在提交之前使用提交前事件处理程序将比赛连接到基于主队的体育场。 即使在这个微流程中没有任何检查,你仍然需要告诉结束事件返回true,这样事件才会真正执行。
构建页面
团队页面
让我们从构建团队页面开始。
-
向 SoccerSquad 模块添加一个新页面。使用以下设置:
- 名称:Team_Overview
- 导航布局:Atlas_Default
- 页面模板:列表 (来自列表部分)
-
使用下图构建概览页面:
- 队长信息(上图中突出显示)使用以下参数显示:
-
将 Add 按钮连接到 Team 实体和新创建的 Team_NewEdit 详细信息页面。对详细信息页面使用以下设置:
- 名称:Team_NewEdit
- 导航布局:Atlas_Default
- 页面模板:Form vertical
-
将详细信息按钮连接到同一页面。
-
使用下图构建Team_NewEdit页面:
- 两列都有类名xs-col-12。
- Heading 2样式。
- 构建块Flex container left。
- Heading 2样式。
- 默认Create object按钮。
- 构建块:List 1 item; On click action -> Show a page -> Player_NewEdit。这个页面应该是一个弹出页面,可以让你填写玩家的名字和号码。
-
将两列Phone的宽度设置为手动 12。
-
将两个标题设置为标题 2 样式。
-
默认创建对象按钮。
-
构建块:列出单行;单击操作 ->显示页面-> Player_NewEdit。这个页面应该是一个弹出页面,可以让你填写队员的名字和号码。
-
将New按钮连接到Player实体,使用Team_Player关联立即设置与团队的连接。还将它连接到Player_NewEdit页面。
-
选择船长的引用选择器需要获取一个数据源微流。否则,它将显示系统中的所有球员,而不仅仅是属于他当前添加的球队的球员。
- 打开引用 选择器的属性并转到可选 对象选项卡。
- 将Source设置为microflow。
- 将其连接到一个新的微流:DS_Team_GetPlayers。
- 使用下图构建微流:
将 Team_Overview 页面添加到您的 Navigation,以便 Adrian 可以访问该页面。
匹配页面
接下来是比赛页面。
-
使用以下设置创建一个新页面:
- 名称:Match_Overview
- 导航布局:Atlas_Default
- 页面模板:List MasterDetail(List部分)
-
使用以下图像构建页面:
A. 使用以下 Xpath 显示匹配项:[StartDateAndTime >= '[%BeginOfCurrentDay%]']
B. 主队对客队 ; _ 渲染模式:标题3;颜色:品牌 原色;对齐方式:C 回车;类:表格标题
C. 这将分别显示StartDateAndTime属性的日期和时间值。样式:标题5;对齐方式:C 输入
D. 底距:外大;类别:card cardmetrics*
E. 样式:标题2;对齐方式:居中;类别:卡片计数器
F. 小部件:数据视图
G. 左列中的Name属性的样式为 Heading 6。
H. StartDateAndTime值与步骤 b 中的值相同,但没有样式。
- Upcoming和Past选项卡显示几乎完全相同的信息,让我们首先关注构建Upcoming选项卡。
- 记分卡应该只对已经结束的比赛可见。为记分卡添加条件 可见性。 使用以下表达式:
-
New按钮应该创建一个新的Match对象并打开一个新创建的Match_NewEdit弹出页面。在此页面上,阿德里安可以:
- 选择匹配的日期和时间,对一个属性使用两个输入小部件。您可以通过放置两个DatePicker小部件来做到这一点。在小部件的“属性”屏幕中,将第一个设置为仅用于日期,将第二个设置为仅用于时间。
- 选择主队
- 选择客队
-
Past选项卡的内容将类似,但有一些更改:它不需要新按钮,并且左侧列中列表视图的 Xpath应更改为 [StartDateAndTime < '[%BeginOfCurrentDay%]']
-
右列与即将到来的选项卡中的列完全相同。那么为什么不把它变成一个可重复使用的片段呢?
- 在匹配数据视图中选择最外层的容器。
- 将片段命名为 SNP_Match_Details。
- 重用过去选项卡中的片段。不要忘记将它嵌套在匹配数据视图中!
- 将 Match_Overview 页面添加到导航菜单。
到这里我们完成了数据模型多重关联关系的学习和演练,下一章我们就一起来看看,什么事非持久化实体,非持久化实体在西门子Mendix中可以做什么?