Динамические пользовательские элементы управления получают и поддерживают значения после обратных передач - PullRequest
5 голосов
/ 25 марта 2011

У меня есть созданная страница, которая динамически генерирует пользовательские элементы управления.Например, пользовательский элемент управления имеет два поля, которые можно редактировать: 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.Кажется, что он отлично работает на исходной обратной передаче, но после последующих обратных передач я все еще получаю старое значение для одного из полей.Как я могу гарантировать, что:

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

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

Ответы [ 2 ]

9 голосов
/ 25 марта 2011

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

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
  }
}
4 голосов
/ 25 марта 2011

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

Несоответствие идентификаторов состояния просмотра приведет к тому, что такие вещи, как метки и литералы, вернутся к исходным значениям. С другой стороны, несоответствие идентификатора данных POST приведет к тому, что поля ввода вернутся к начальным значениям. Если у вас возникают проблемы с возвратом полей ввода к начальным значениям, изменение состояния просмотра не решит проблему. Распространенным заблуждением является то, что значения полей сохраняются в состоянии просмотра. Однако в этом нет необходимости, поскольку значения поля ввода уже содержатся в данных POST. Для хорошего обсуждения того, как работает состояние просмотра, см. Понимание того, как работает состояние просмотра Скотта Митчелла.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...