【问题标题】:Dynamically Change User Control in ASP.Net在 ASP.Net 中动态更改用户控件
【发布时间】:2009-06-12 16:34:30
【问题描述】:

我正在尝试创建一个网页,该网页将根据下拉列表的选定值显示适当的用户控件。

基本上页面布局是这样的:

下拉选择
基于下拉选择创建的用户控件 >

I have it half working... the controls are changing when the selection changes. 在 OnInit() 中,我动态创建了最后一个选定的控件(其值保存在会话状态中,因为 ViewState 在 OnInit 中不可用)。

当下拉选择发生变化时,我删除了旧的用户控件,并添加了一个新控件。 问题是:从选择更改事件中添加新控件后,我无法在第一次回发时保存用户的更改。第一次回发后,从 OnInit 而不是 Change 事件创建所选控件,并从那时起保存状态,直到下一次选择更改。

这里是 SelectionChanged 方法:

protected void SelectionChanged(object sender, EventArgs e)
{
    SelectedValue = int.Parse(DropDownList.SelectedValue);  //Store in Session
    Control userControl = GetSpecificUserControl(SelectedValue);
    PlaceHolder1.Controls.Clear();   // Remove old user control
    PlaceHolder1.Controls.Add(userControl);
}

在 SelectionChanged 发生后用户对新控件所做的任何更改都不会保存在以下回发中。但是,随后的回发确实会被保存。此时,控件正在 OnInit() 中创建。

当控件发生变化时,有没有办法强制正确的回发和 ViewState?控件更改后是否可以强制重新初始化页面?

【问题讨论】:

    标签: asp.net dynamic-controls


    【解决方案1】:

    您需要做的是在 Session 中保留 DropDownList 的最后一个已知值。那么:

    OnInit:

    • 创建会话中保存的值指示的任何控件

    SelectionChanged 事件

    • 删除您在 OnInit 期间创建的任何内容
    • 根据新的 DropDownList 选择创建和添加新控件
    • 在会话中保存新的 DropDownList 选择

    这样,在更改后的下一次回发中,您将重新创建 ViewState 期望找到的控件,因此将恢复其状态。

    动态控件可能非常挑剔。通常更容易创建您可能需要的所有控件并将其 Visible 属性设置为 false。这样它们根本不会呈现给浏览器。然后将 Visible 设置为 true,以便在需要时仅针对需要的控件。

    【讨论】:

    • 不幸的是,这已经是我所做的。 (SelectedValue 是导致值存储在会话中的属性。)问题是新创建的控件在下一次回发时没有保存更改。
    • 这是因为尚未为新控件 ID 保存 ViewState,并且 ViewState 不希望看到它。您需要使用 ViewState 注册您的控件 - 我建议我的解决方案 #1,否则 Joel 建议添加所有控件并使它们不可见。请记住,设置 Visible=false 意味着不呈现任何内容 - 因此,如果您拥有的控件数量是可管理的,这通常是一个很好的解决方案。
    • +1 用于防止进一步脱发。我所要做的就是将我的持久值之一切换为存储在 Session 而不是 ViewState 中,就好像它开始工作一样!
    • when 这只是一个存档评论,可以添加到@grimus 所经历的内容中。如果您不小心始终为重新创建的控件显式设置相同的控件 ID,那么他描述的确切问题可能会发生(当像上面 Joel 描述的那样使用 oninit / event 构建时)。
    【解决方案2】:

    这是 ASP.Net 网络表单的经典问题。您有多种选择:

    1) 这有点像 hack,因为它有点超出预期的页面生命周期,但根据我的经验,这是处理问题的最直接方法。当页面从下拉选择事件返回时,只需在Init() 期间轮询Request["MyDropDownID"] 以获取下拉控件的选定值 - 不要等待OnMyDropDownChanged() 事件来设置您的页面。

    2) 为您的用户控件实现您自己的 ViewState 处理。这需要深入研究 ViewState 文档并覆盖许多方法。

    3) Joel 的解决方案。他打败了我,但我试图获得第一篇文章:p

    其他选项涉及使用 javascript 等发布值,但那些变得非常混乱。

    【讨论】:

    • 如何确定 Request["MyDropDownID"] 的字符串?
    • DropDown1.UniqueID 真是个菜鸟!
    • 是的!这行得通!谢谢你,谢谢你,谢谢你!我觉得我应该为其他人指出这一点...... ASP.Net 非常挑剔。在遵循 womp 的 Request 方法之后,如果我做了 OnInit() { PlaceHolder.Controls.Add(oldcontrol); PlaceHolder.Controls.Clear(); PlaceHolder.Controls.Add(newControl); } ...它没有工作。如果我这样做: PlaceHolder.Controls.Add(newControl); ...然后它确实有效!万岁!
    • +1 表示 Request[...] 建议。直到现在我都为此发疯了。
    • +1 对于我的 Request[...] 建议。非常感谢。
    【解决方案3】:

    如果选项列表不是太大,您可以静态渲染所有用户控件,并使用 JavaScript/jQuery 根据下拉列表的值显示/隐藏相应的控件(onchange js 事件)。保存时,您可以使用下拉值从用户控件中提取适当的值。

    您可以避免处理动态控件的痛苦,在从下拉列表中选择时提供更灵敏的 UI(无回发)等...

    【讨论】:

      【解决方案4】:

      不要在 SelectedIndexChanged 处理程序中添加控件,在 Page_Load 期间添加它。您只需在每次页面加载时测试下拉列表的值,并为该值加载正确的控件。

      【讨论】:

      • 不!不要在页面加载期间添加动态控件。已经太晚了。
      • 这不能解决问题。加载 ViewState 后仍然会发生 Page_Load()。
      • 那是 ASP.Net 1.1 吗?
      • btw..这将加载发布的值,但不会加载状态。
      • 原来是的,现在是 3.5。您可能对状态是正确的,我只关心值...(无论如何用动态数据重写整个事情,似乎可以更好地管理整个情况)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-11
      • 2013-11-17
      • 1970-01-01
      • 2023-04-09
      • 2015-02-14
      相关资源
      最近更新 更多