2011-03-25 4 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 컬렉션을 다시 만들고 있기 때문에 정보를 저장하고 올바르게 유지하는 데 문제가 있습니다. inital postback에서 잘 작동하는 것처럼 보이지만 후속 postback 후에도 필드 중 하나에 대해 이전 값을 얻습니다. 어떻게해야합니까 :

1) 정보가 사용자 정의 컨트롤에 올바르게 설정되었습니다. viewContent를 참조하는 public 속성을 에 넣어야합니까? UserControl 속성마다?

2) 저장 이벤트를 클릭 한 후 다시 게시 한 후에 컨트롤을 다시 작성해도 초기로드의 "이전"값은 유지되지 않습니까? viewstate는 어떻게 처리해야합니까? 데이터가 사용자가 변경 한 내용을 반영하도록합니다.

+0

나는 당신의 코드를 따르려고 노력하고 있는데, 따라하기 힘든 몇 가지 문제가있다. 'InitControls()'에서'foreach' 루프가 있지만, 단순한 루프가되도록하려는 것 같습니까? 즉 for (int i = 0; i

+0

@Joel : 긴 하루였습니다 ... 나는 수정했습니다 :) –

답변

9

view-state/control-state가 올바르게 작동하려면 사용자 컨트롤에 대해 동일한 ID가 있어야합니다. ID를 명시 적으로 지정하지 않으므로 ID가 생성되어야하며 사용자 정의 컨트롤이 두 개 이상있는 경우 충돌이 발생합니다. 포스트 백 (post-back)을 통해 동일한 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. 동적으로 생성 된 컨트롤의 수가 변경되거나 생성 된 순서가 변경되면 동적으로 생성 된 웹 컨트롤과 뷰 상태의 해당 개체에 대한 상태 정보가 일치하지 않게됩니다. 마찬가지로 동적으로 생성 된 웹 컨트롤의 ID와 POST 헤더의 쿼리 매개 변수 ID가 일치하지 않습니다. 즉, 일부 필드의 값은 POST 데이터에서 업데이트되지 않습니다.

뷰 상태 ID가 일치하지 않으면 레이블 및 리터럴과 같은 항목이 초기 값으로 되돌아갑니다. 반면 POST 데이터 ID가 일치하지 않으면 입력 필드이 원래 값으로 되돌아갑니다. 입력 필드가 초기 값으로 돌아가는 데 문제가있는 경우 뷰 상태로 돌아 가면서 문제가 해결되지 않습니다. 필드 값이 뷰 상태에서 유지된다는 것은 일반적인 오해입니다. 그러나 입력 필드 값이 이미 POST 데이터에 포함되어 있기 때문에 이는 필요하지 않습니다. View State 작동 방식에 대한 자세한 내용은 Scott Mitchell의 Understanding how the viewstate works을 참조하십시오.

VinayC가 지적한 것처럼 동일한 순서로 항상 동적으로 추가 된 컨트롤을 만드는 경우 "ID1", "ID2", "ID3"등과 같은 일련의 ID를 생성 할 수 있습니다. 웹 컨트롤을 만듭니다. 귀하의 경우에는 사용자 정의 컨트롤 필드 값을 데이터베이스에 저장하므로 각 사용자 정의 컨트롤에 대해 새 ID를 한 번만 생성하고 생성 된 각 ID를 연관된 필드 값과 함께 데이터베이스에 저장할 수 있습니다. 그렇게하면 컨트롤을 만드는 순서에 대해 걱정할 필요가 없습니다.

관련 문제