2011-03-25 35 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與關聯的字段值一起存儲在數據庫中。這樣,您不必關心您創建控件的順序。

相關問題