在/Teams/Details?id=xxx的页面,有这样一个控件,使得不需要回到/Teams/Index就能轻松切换团队:
由于这种团队切换控件比比皆是,比如在团队故事板中(以及其他地方若干处):
所以希望开发一个控件。
这个控件应该能:
1. 里边所包含的链接自动跟随页面的链接。
比如第一张图里边,指向/Teams/Details?id=XXX;而第二张图里边,则是指向/Agile/TeamStoryBoards/Details?teamID=xxx
2. 下拉菜单里边的所有链接,会因为id或teamID不同而指向指定团队的页面。
<div class = "link-span spliter"> 切换团队:@Team.TeamsDropdownList(this, "id") </div>
public partial class Team : Department { public static HelperResult TeamsDropdownList(WebViewPage page, string urlKey) //urlKey就是"id"或"teamID"这两个,用来表示需要替换URL中的哪个参数的 { var currentTeamID = page.ParameterOf(urlKey); //提取id或teamID的实际值,里边利用了page.Request.RawUrl,也可以用page.Request.Queries(我们以前不知道有这个)。 var program = Program.Default(); //取得缺省部门,部门是团队Team的上一个级别。 var currentTeam = string.IsNullOrEmpty(currentTeamID) ? null : program.Teams().Single(i => i.ID.ToString() == currentTeamID); //下拉菜单中的当前团队。 return MFCUI.DropdownListHtml(page, currentTeam == null ? new MvcHtmlString("选择团队") : MFCUI.ImageLink(currentTeam.Title, page.Request.RawUrl, displayAsBoldTextOnPage: page), program.Teams().Select(i => MFCUI.ImageLink(i.Title, page.MergeParameter(urlKey, i.ID.ToString()), displayAsText: currentTeam != null && i.ID == currentTeam.ID))); }
page.MergeParameter(urlKey, i.ID.ToString())这句话把page.Request.RawUrl中的"id"或"teamID"替换为program.Teams()中不同团队的ID,生成其新链接。
<div class="link-span spliter"> 切换产品:@Product.ProductsDropdownList(this, "id") </div>
public static HelperResult ProductsDropdownList(WebViewPage page, string urlKey) { var currentTeamID = page.ParameterOf(urlKey); var productLine = ProductLine.Default(); var currentProduct = string.IsNullOrEmpty(currentTeamID) ? null : productLine.Products().Single(i => i.ID.ToString() == currentTeamID); return MFCUI.DropdownListHtml(page, currentProduct == null ? new MvcHtmlString("选择团队") : MFCUI.ImageLink(currentProduct.Title, page.Request.RawUrl, displayAsBoldTextOnPage: page), productLine.Products().Select(i => MFCUI.ImageLink(i.Title, page.MergeParameter(urlKey, i.ID.ToString()), displayAsText: currentProduct != null && i.ID == currentProduct.ID))); }这两个方法的内容几乎完全相同,这是代码坏味道的先兆;比如以后修改了MFCUI.DropdownListHtml,就要回来修改两个地方。
public static HelperResult BrothersDropdownList(WebViewPage page, string defaultText, Item father, string whattype, string urlKey) { var currentId = page.ParameterOf(urlKey); var currentItem = string.IsNullOrEmpty(currentId) ? null : father.SubItems().Single(i => i.ID.ToString() == currentId); return MFCUI.DropdownListHtml(page, currentItem == null ? new MvcHtmlString(defaultText) : MFCUI.ImageLink(currentItem.Title, page.Request.RawUrl, displayAsBoldTextOnPage: page), father.SubItems().Where(i => i.WhatType == whattype).Select(i => MFCUI.ImageLink(i.Title, page.MergeParameter(urlKey, i.ID.ToString()), displayAsText: currentItem != null && i.ID == currentItem.ID))); }
father.SubItems().Where(i => i.WhatType == whattype)就是问father的下一级别中的whattype类型的。这样如果传入father=ProductLine.Default()和whattype=ItemWhatType.ProductProduct,就能得到所有产品,和原来代码结果相同。
<div class="link-span spliter"> 切换产品:@Product.ProductsDropdownList(this, "id") 切换产品:@Product.BrothersDropdownList(this, "切换产品", ProductLine.Default(), ItemWhattype.ProductProduct, "id") </div>最好的测试方法,就是像上面这样做“对比测试”,然后看两者有何不同;这个很像敏捷开发里边提到重构时,要验证产品的外部功能没有发生变化一样。
<div class="link-span spliter"> 切换产品:@Product.ProductsDropdownList(this, "id") 切换产品:@Product.BrothersDropdownList(this, "切换产品", ProductLine.Default(), ItemWhattype.ProductProduct, "id") 切换产品:@Item.BrothersDropdownList(this, "切换产品", ProductLine.Default(), ItemWhattype.ProductProduct, "id") </div>