我正在将ASP.NET MVC 2&NET 3.5与Visual Studio 2008一起使用。
好的,我所指的“向导式页面导航”是一个站点,在该站点中,您有给定流程或工作流中的阶段列表。有一些视觉符号可以指示你所处阶段的哪一部分。我已经通过以下方式实现了这一部分(尽管它有点像黑客程序):
css class current表示活动页。
css class notcurrent在活动页(即您不在的页)中表示
我在名为navigationtracker的类中声明了以下方法。
public static String getCss(String val, String currView)
{
String result = String.Empty;
String trimmedViewName = currView.Substring(currView.LastIndexOf("/") + 1).Replace(".aspx", "");
if (val.ToLower().Equals(trimmedViewName.ToLower()))
result = "current";
else
result = "notcurrent";
return result;
}
我的舞台在这样的控制下:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%@ Import Namespace="TheProject.Models" %>
<link href="../../Content/custom.css" rel="stylesheet" type="text/css" />
<%
String currentView = ((WebFormView)ViewContext.View).ViewPath;
%>
<table width="100%">
<tr>
<td class="<%= NavigationTracker.getCss("LogIn",currentView)%>" style="width:18%;">Log In</td>
<td class="<%= NavigationTracker.getCss("YearSelect",currentView)%>" style="width:18%;">Year Section</td>
<td class="<%= NavigationTracker.getCss("GoalEntry",currentView)%>" style="width:18%;">Goals</td>
<td class="<%= NavigationTracker.getCss("AssessmentEntry",currentView)%>" style="width:18%;">Assessment</td>
<td class="<%= NavigationTracker.getCss("SummaryEntry",currentView)%>" style="width:18%;">Summary</td>
</tr>
</table>
这是我需要帮助的地方。
为了补充这个过程,我想创建一个用户控件,它只有上一个和下一个按钮来管理整个过程。到目前为止,我遇到的一个问题是,这个控件不能放在母版页中,但必须在表单结束之前包含在每个视图中。我不太介意。单击“上一步”或“下一步”按钮,将包含表单提交到相应的操作;但是,我不确定如何执行以下操作:
1)检测是否单击了上一个或下一个按钮
2)分别在流程开始和结束时显示/隐藏上一个和下一个按钮的逻辑。
对于我的应用程序,我注意到的另一个奇怪之处是,在浏览了流程的几个页面之后,如果我单击后退按钮,我的模型中的一些值将填充在页面上,而其他的则不会。例如,为文本区域输入的文本会显示,但尚未选择为单选按钮选择的值,但是在直接检查模型时,适当的对象确实具有要绑定到该单选按钮的值。
我可能只需要把最后一部分放到一个新问题中。我的主要问题是导航控制。处理该逻辑的任何指针或提示,以及检测是否单击了下一个或上一个,都将是最有用的。
编辑1
我曾想过在控件中放置一个隐藏字段,显示上一个和下一个按钮。根据单击的按钮,我将使用javascript更新隐藏字段值。现在的问题似乎是,隐藏字段从未与表单一起创建或提交。我已经修改了controller post参数以接受附加字段,但它从未被提交,也不在formcollection中。
这是隐藏字段的代码。请注意,它是在一个用户控件中生成的,该控件在父级视图的窗体内部调用(希望这是有意义的)。
<% Html.Hidden("navDirection", navDirection); %>
思想?
编辑2
我已经解决了所有这些问题。我最迟将在星期二详细发布代码。下面给出的解决方案可能会被选为答案,因为这使我的思考过程正确。
简而言之,解决方案是使用一个类似于逻辑建议的导航类,根据当前视图和所有视图的字符串列表确定下一页或上一页。创建了一个部分视图/用户控件以显示上一个/下一个按钮。用户控件有两个隐藏字段:1)一个字段具有当前视图的值;2)一个字段指示导航方向(上一个或下一个)。javascript用于根据单击的按钮更新隐藏的导航字段值。与当前视图相比,用户控件中的逻辑决定是否显示“上一个”或“下一个”按钮,具体取决于向导中的第一个和最后一个视图。
都说了,我对结果很满意。当我回到这里的时候,我可能会发现一些代码气味的问题,但目前为止,它是有效的。
谢谢大家的帮助!
编辑3-解决方案
以下是我为显示“下一步”和“上一步”导航按钮而构建的控件的代码:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%@ Import Namespace="Project.Models" %>
<link href="../../Content/custom.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" >
function setVal(val) {
var nav = document.getElementById("NavigationDirection");
nav.value = val;
}
</script>
<%
String currentView = ((WebFormView)ViewContext.View).ViewPath;
String navDirection = "empty";
currentView = NavigationTracker.getShortViewName(currentView);
%>
<input type="hidden" value="<%= currentView %>" name="CurrentView" id="CurrentView" />
<input type="hidden" value="<%= navDirection %>" name="NavigationDirection" id="NavigationDirection" />
<% if( currentView != NavigationTracker.FirstPage) { %>
<div style="float:left;">
<input type="submit" value="Previous" onclick="setVal('previous')" /> <!-- On click set navDirection = "previous" -->
</div>
<% } %>
<% if (currentView != NavigationTracker.LastPage)
{ %>
<div style="float:right;">
<input type="submit" value="Next" onclick="setVal('next')" /> <!-- On click set navDirection = "next" -->
</div>
<% } %>
从这里开始,在您想要的视图上的表单结束标记之前呈现控件,如下所示:
<% Html.RenderPartial("BottomNavControl"); %>
<% } %>
现在我不能真正地发布所有的导航跟踪器代码,但是它的工作原理可以从选择的答案和下面的代码片段推断出来,这些代码片段根据当前视图和方向(上一个或下一个)返回视图的名称。
public String NextView
{
get
{
if (String.IsNullOrEmpty(this.NavigationDirection)) return string.Empty;
int index = this.MyViews.IndexOf(this.CurrentView);
String result = string.Empty;
if (this.NavigationDirection.Equals("next") && (index + 1 < MyViews.Count ))
{
result = this.MyViews[index + 1];
}
else if (this.NavigationDirection.Equals("previous") && (index > 0))
{
result = this.MyViews[index - 1];
}
return result;
}
}
现在,做所有这些都有一些副作用,很容易被认为是代码味道。首先,我必须修改所有标记为[httppost]的控制器方法,以接受NavigationTracker对象作为参数。此对象包含帮助器方法和CurrentView&NavigationDirection属性。完成后,我可以以相同的方式在所有操作中获得下一个视图:
return RedirectToAction(nav.NextView);
其中nav类型为navigationtracker。
另一个注意事项是navigationtracker的firstpage&lastpage属性是静态的,因此我实际上在global.asax.cs文件中使用navigationtracker.firstpage进行路由。这意味着我可以转到我的NavigationTracker类,在一个地方为整个应用程序更改流。
我希望对这个解决方案有任何评论或批评。我承认这可能不是一个很好的解决方案,但乍一看,我很满意。
希望它有帮助。