2011-03-25 2 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 со значениями из базы данных. Пользователь должен иметь возможность изменять большинство (но не всех) этих полей. Пользователь не должен изменять идентификатор, но мне нужно его обновить запись в базе данных.

У меня возникли проблемы с получением информации для сохранения и сохранения, потому что я воссоздаю коллекцию MyUserControl. Кажется, что он отлично работает на основе обратной обратной связи, но после последующих postbacks я все еще получаю старое значение для одного из полей. Как я могу убедиться, что:

1) Информация правильно установлена ​​на пользовательские элементы управления. Нужно ли включать публичное свойство, ссылающееся на viewstate на каждый свойство UserControl?

2) После нажатия события сохранения после обратной передачи перестройка элементов управления не заставит меня сохранить какие-либо «старые» значения от начальной загрузки? Как мне обращаться с представлением здесь? Я хочу, чтобы данные отражали то, что изменил пользователь.

+0

Я пытаюсь следовать вашему коду, есть несколько проблем, из-за которых трудно следовать. В 'InitControls()' у вас есть цикл foreach', но я думаю, вы намерены, что это простой цикл, не так ли? то есть 'for (int i = 0; i

+0

@Joel: Это был долгий день ... Я внес коррективы :) –

ответ

9

Для правильной работы состояния представления/состояния управления у вас должен быть одинаковый идентификатор для ваших элементов управления. Поскольку вы не назначаете идентификатор явно, он должен быть сгенерирован, и там будут конфликты с присутствием более одного пользовательского элемента управления. Я порекомендую вам иметь какую-то логику для создания одинакового набора идентификаторов по обратной стороне. Например,

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

Как отметил VinayC, основная проблема здесь связана с тем, что, когда вы динамически добавлять элементы управления на страницу, если не назначать идентификаторы для этих элементов управления, они будут даваться генерироваться идентификаторы. Если число динамически сгенерированных элементов управления изменяется или если порядок, в котором они созданы, изменяется, тогда будет существовать несоответствие между динамически создаваемыми веб-элементами управления и информацией о состоянии для этих объектов в состоянии представления. Точно так же будет несоответствие между идентификаторами динамически создаваемых веб-элементов управления и идентификаторами параметров запроса в заголовках POST. Это означает, что значения некоторых полей не будут обновляться из данных POST.

Просмотр несоответствий идентификатора штата приведет к тому, что подобные метки и литералы вернутся к исходным значениям. С другой стороны, несоответствия ID данных POST вызовут поля ввода, чтобы вернуться к значениям inital. Если у вас возникли проблемы с возвратом полей ввода к исходным значениям, обход с состоянием представления не решит проблему. Это распространенное заблуждение, что значения поля сохраняются в состоянии представления. Однако это необязательно, поскольку значения поля ввода уже содержатся в данных POST. Для хорошего обсуждения того, как работает государство просмотра, см. Understanding how the viewstate works от Скотта Митчелла.

Если вы всегда создаете свои динамически добавленные элементы управления в том же порядке, то, как указывает VinayC, вы можете сгенерировать последовательность идентификаторов, таких как «ID1», «ID2», «ID3», ... как вы создание веб-элементов управления. В вашем случае, поскольку вы сохраняете значения поля User Control в базе данных, вы можете генерировать новые идентификаторы для каждого пользовательского элемента управления только один раз и хранить каждый сгенерированный идентификатор в базе данных вместе с соответствующими значениями полей. Таким образом, вам не нужно беспокоиться о порядке, в котором вы создаете элементы управления.

Смежные вопросы