这是一个令人烦恼的问题——当您想要在 ASP.NET Web 表单中使用动态控件时,您必须选择两害相权取其轻。最终,归结为您要做出哪种妥协:视图中的演示者关注点或演示者中的视图关注点。
当我在 Web 表单中工作时,我通常更喜欢后者 - 我接受演示者与 ASP.NET 页面生命周期相关联,并创建一个 InitializeView 方法来执行创建动态控件所需的任何操作:
// Presenter
// This could also be parameterless if you prefer that idiom but
// then the view needs a SelectedState property that serves up values
// straight from the Form collection, and it won't be obvious why.
public void InitializeView(string selectedState) {
if (selectedState != null) {
view.Counties = dataLayer.GetCounties(selectedState);
}
}
// View
protected void Page_Init(object sender, EventArgs args) {
presenter.InitializeView(Request.Form["StateList"]);
// ... build counties drop-down ...
}
当然,这将演示者的语义与 ASP.NET 生命周期联系在一起,并掩盖了该方法中发生的事情。您可以通过给 InitializeView 一个更具描述性的名称来缓解这种情况,例如 ProcessSelectedState,但除非方法名称引用页面生命周期,否则永远不会很明显为什么您不只是使用模型的其余部分获取县(在presenter.LoadModel 或任何你可能称呼它的地方)。
我可以看到替代方案的吸引力:
protected void Page_Init(object sender, EventArgs args) {
if (Request.Form["StateList"] != null) {
List<string> counties = presenter.GetCounties(Request.Form["StateList"]);
// ... build counties drop-down ...
}
}
Presenter 的语义非常清楚 - 很容易理解 GetCounties 的作用,它与页面生命周期没有任何关系。但是你的视图中有可测试的东西,这很糟糕,这对我来说通常比让我的演示者不了解他们的视图引擎更重要。
另一种选择是在页面初始化期间仅加载您的整个模型。您的服务器控制值将不可用,因此您必须从Request.Form 获取任何这些值。不过,这不是惯用的 ASP.NET 经典——它可能会过度混淆,因为大多数 Web 表单开发人员习惯于直接从 Web 控件而不是直接从 POST 数据中获取值。