2011-03-25 72 views
5

我有一个页面,我已经建立了动态​​生成用户控件。例如,用户控件有两个可以编辑的字段: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)点击保存事件后,回发后,重建控件不会导致我保留初始加载的任何“旧”值?我应该如何处理视图状态?我希望数据能够反映用户的变化。

+0

我想跟着你的代码有一些问题,使它很难遵循。在'InitControls()'你有一个'foreach'循环,但是我认为你打算做一个简单的循环,不是吗?即'for(int i = 0; i 2011-03-25 04:38:14

+0

@Joel:这是一个漫长的一天......我已经做出了更正:) – 2011-03-25 05:01:50

回答

9

要使视图状态/控件状态正常工作,您的控件必须具有相同的ID。由于您没有明确指定ID,因此必须生成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 
    } 
} 
+0

+1这确实是这里的核心问题。我将发布另一个答案以进一步详细说明。 – 2011-03-25 06:16:42

+0

这解决了这个问题。感谢您的输入。 – 2011-03-25 16:10:37

4

正如指出的VinayC,这里的根本问题是由于这样的事实,当你动态控件添加到页面,如果你不分配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”......创建Web控件。在你的情况下,因为你将用户控制字段值存储在数据库中,所以你可能只想为每个用户控件生成一次新的ID,并将每个生成的ID与关联的字段值一起存储在数据库中。这样,您不必关心您创建控件的顺序。