2011-03-25 22 views
5

ユーザーコントロールを動的に生成している私が構築したページがあります。たとえば、ユーザーコントロールには、編集可能な2つのフィールド、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つに古い値が残っています。

1)情報がユーザーコントロールに正しく設定されていること。 UserControlのプロパティごとに、ビューステートを参照するpublicプロパティをに配置する必要がありますか?

2)保存イベントをクリックした後、ポストバック後、コントロールを再構築しても、最初の負荷からの「古い」値は保持されません。ここでviewstateをどのように扱うべきですか?ユーザーが変更した内容を反映させたい

+0

私はあなたのコードに従うことを試みていますが、それに追従するのが難しいいくつかの問題があります。 'InitControls()'には 'foreach'ループがありますが、単純なループであることを意図していると思いますか?すなわちfor(int i = 0; i

+0

@Joel:それは長い一日だった...私は修正を行った:) –

答えて

9

view-state/control-stateが正しく機能するためには、自分のコントロールに同じ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これは確かにここでの中心的な問題です。私はもう少し詳細に行く別の答えを投稿するつもりです。 –

+0

これで問題は解決しました。あなたのご意見ありがとうございます。 –

4

としては、ここでの根本的な問題は、あなたがこれらのコントロールのIDを割り当てていない場合は、動的に彼らが生成与えられます、ページにコントロールを追加するという事実によるVinayCが指摘しましたID。動的に生成されたコントロールの数が変更された場合、または作成された順序が変更された場合は、動的に作成されたWebコントロールとビューステートのそれらのオブジェクトの状態情報が不一致になります。同様に、動的に作成されたWebコントロールのIDと、POSTヘッダー内のクエリパラメータのIDとの間に不一致があります。つまり、一部のフィールドの値はPOSTデータから更新されません。

ビューの状態IDの不一致により、ラベルやリテラルなどの値が初期値に戻ってしまいます。一方、POSTデータIDの不一致は入力フィールドを元の値に戻すことになります。入力フィールドが初期値に戻って問題が発生している場合は、ビューステートを使って問題を解決することはできません。フィールド値がビューステートに保持されるのはよくある誤解です。ただし、入力フィールドの値はすでにPOSTデータに含まれているため、これは不要です。ビューステートの仕組みの詳細については、Scott MitchellのUnderstanding how the viewstate worksを参照してください。

VinayCが指摘しているように、常に動的に追加されたコントロールを同じ順序で作成すると、「ID1」、「ID2」、「ID3」などの一連のIDを生成することができますWebコントロールを作成します。あなたの場合、データベースにユーザーコントロールのフィールド値を格納しているので、ユーザーコントロールごとに新しいIDを1回だけ生成し、生成された各IDを関連するフィールド値と共にデータベースに格納することができます。そうすれば、コントロールを作成する順番を気にする必要はありません。

関連する問題