【问题标题】:Dynamic User Controls get and maintain values after postbacks动态用户控件在回发后获取和维护值
【发布时间】:2011-07-22 15:43:36
【问题描述】:

我已经构建了一个动态生成用户控件的页面。例如,用户控件有两个可以编辑的字段:SomeId 和 SomeData。我希望能够基于UserControlObject 设置这些值。之后当我读取控件时,我希望能够从控件返回 UserControlObject 并将数据库值设置为该值。我无法让这些值保持最新状态。

//Page
public class SomePage
{
    private List<MyUserControl> _MyUserControls;

    private void InitControls()
    {
      var controlsToBuild = SomeDatabaseCallToGetControlObjects();

          foreach(MyUserControl control in controlsToBuild)
          {
        MyUserControl control = this.Page.LoadControl("MyControl.ascx") as MyUserControl;

          UserControlPlaceHolder.Controls.Add(myControl);
          _MyUserControls.Add(myControl);
      }
    }

    protected void Page_Init(object sender, EventArgs e)
    {
       InitControls();
    }

    protected void SaveButton_Click(object sender, EventArgs e)
    {
      if (this.IsValid)
      {
        List<MyUserObject>listObj = new List<MyUserObject>();
        foreach(MyUserControl control in _MyUserControls)
        {
           MyUserObject obj = control.GetObjectFromControl();
           listObjs.Add(obj);
        }
        SaveToDatabase(listObjs);
        //Clear placeholder in case number of controls has changed based on the save
        UserControlPlaceHolder.Clear();
        InitControls();
        GetObjectFromDatabase();
      }
    }

}

//Object to put in control
public class UserControlObject
{
    public string DataForUser { get;set;}
    public double MoreDataForUser { get;set;}
    public int HiddenIdFromUser { get; set;}
}


//User control
public class MyUserControl : UserControl
{

  public MyUserControlObject GetObjectFromControl()
  {
     UserControlObject obj = new UserControlObject();
     obj.DataForUser = textBoxOnTheControl.Text;
     obj.MoreDataForUser = anotherBoxOnTheControl.Text;
     obj.HiddenIdFromUser = hiddenField.Value;

     return obj;
  }

  public void SetUserControlObject(UserControlObject obj)
  {
     textBoxOnTheControl.Text = obj.DataForUser;
     anotherBoxOnTheControl.Text = obj.MoreDataForUser;
     hiddenField.Value = obj.HiddenIdFromUser;
  }
}

基本上,我想为每个MyUserControl 加载数据库中的值。用户应该能够更改大部分(但不是全部)这些字段。用户应该不能更改 ID,但我需要它来更新数据库中的记录。

我在获取信息以正确保存和保留时遇到了一些问题,因为我正在重新创建 MyUserControl 的集合。它似乎在初始回发时工作正常,但在随后的回发之后,我仍然得到其中一个字段的旧值。我如何确保:

1) 信息已正确设置到用户控件。我是否需要在 UserControl 的 每个 属性上放置一个引用视图状态的公共属性?

2) 单击保存事件后,在回发后,重建控件不会导致我保留初始加载的任何“旧”值?我应该如何处理这里的视图状态?我希望数据能够反映用户所做的任何更改。

【问题讨论】:

  • 我正在尝试遵循您的代码,但存在一些难以遵循的问题。在InitControls() 中,您有一个foreach 循环,但我认为您打算将其作为一个简单的循环,不是吗?即for (int i=0; i&lt;numControlsToBuild) .... Also, the code is modifying the loop variable control, which can't be what you want. At the end, the method SetUserControlObject`忽略传入参数obj,然后有几个对_UserControlObject的引用。你的意思是在那里引用obj
  • @Joel:这是漫长的一天......我已经进行了更正:)

标签: c# asp.net user-controls


【解决方案1】:

要使视图状态/控件状态正常工作,您的控件必须具有相同的 ID。由于您没有明确分配 ID,因此必须生成它,并且存在多个用户控件时会发生冲突。我会建议您使用某种逻辑来通过回发生成相同的 ID 集。例如,

private void InitControls()
{
  var numControlsToBuild = SomeDatabaseCallToGetNumControls();
  int idCounter = 1;
  foreach(var controlData in numControlsToBuild)
  {
    var control = this.Page.LoadControl("MyControl.ascx") as MyUserControl;
    control.ID = "MyControl" + idCounter.ToString();
    idCounter++;
    UserControlPlaceHolder.Controls.Add(myControl);
    _MyUserControls.Add(control);

    // probably code load control data into control
  }
}

【讨论】:

  • +1 这确实是这里的核心问题。我将发布另一个答案以更详细地介绍。
  • 这解决了问题。感谢您的意见。
【解决方案2】:

正如 VinayC 所指出的,这里的根本问题是由于当您将控件动态添加到页面时,如果您不为这些控件分配 ID,它们将被赋予生成的 ID。如果动态生成的控件的数量发生了变化,或者它们的创建顺序发生了变化,那么动态创建的 Web 控件与视图状态中这些对象的状态信息之间就会出现不匹配。同样,动态创建的 Web 控件的 ID 与 POST 标头中查询参数的 ID 之间也会出现不匹配的情况。这意味着某些字段的值不会从 POST 数据中更新。

视图状态 ID 不匹配会导致标签和文字等内容恢复为初始值。另一方面,POST 数据 ID 不匹配会导致 输入字段 恢复为初始值。如果您在输入字段恢复为初始值时遇到问题,那么在视图状态中胡乱处理不会解决问题。字段值在视图状态中持久存在是一个常见的误解。但是,这是不必要的,因为输入字段值已包含在 POST 数据中。有关 View State 如何工作的详细讨论,请参阅 Scott Mitchell 的 Understanding how the viewstate works

如果您始终以相同的顺序创建动态添加的控件,那么正如 VinayC 指出的那样,您可以在创建时生成一系列 ID,例如“ID1”、“ID2”、“ID3”……网络控件。在您的情况下,由于您将用户控件字段值存储在数据库中,您可能只想为每个用户控件生成一次新 ID,并将每个生成的 ID 与关联的字段值一起存储在数据库中。这样,您就不必担心创建控件的顺序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 1970-01-01
    相关资源
    最近更新 更多