Вставьте динамические элементы управления в середину коллекции элементов управления.

StackOverflow https://stackoverflow.com/questions/570056

Вопрос

это мой самый первый пост!Я в отчаянии, поэтому делаю все возможное, чтобы выйти за рамки стандартного поиска в Google.Я считаю, что это вопрос .NET для продвинутого или экспертного уровня.

Проблема в том, что я создал веб-приложение .NET, которое должно иметь возможность динамически вставлять пользовательские элементы управления в середину списка.Меня вполне устраивают динамические элементы управления, поэтому их нужно добавлять только в конец списка (т. е.:Я знаком с такими статьями: http://msdn.microsoft.com/en-us/library/ms972976.aspx).Однако, если мне нужно добавить UserControl в начало коллекции Controls или где-то посередине, я в значительной степени растеряюсь, поскольку уникальный идентификатор элемента управления сбрасывается.

В качестве упрощенного примера предположим, что у меня есть панель, в которую я добавляю список пользовательских элементов управления под названием MyControl.ascx.У меня также есть какое-то событие, которое может быть запущено на странице, и для этого необходимо динамически вставить MyControl.ascx в указанный индекс коллекции Controls панели.У меня также есть одно или несколько событий в MyControl.ascx, на которые мне нужно подписаться.Это означает, что элементы управления должны быть загружены ДО того, как события в этих элементах управления сработают, иначе они не сработают.Если вы не понимаете, о чем я, то либо я плохо сформулировал вопрос, либо этот вопрос может оказаться для вас слишком сложным :)

Ниже приведен псевдокод C#, демонстрирующий проблему.Проблема в том, что метод Controls.AddAt(index, control) НЕ корректирует значения UniqueID элементов управления соответствующим образом.Например, рассмотрим следующие элементы управления в коллекции Controls:

Независимо от того, пишу ли я код, который напрямую зависит от UniqueID или нет, .NET косвенно использует UniqueID для связи событий, которые были запущены при предыдущей обратной передаче, с элементами управления, загружаемыми при новой обратной передаче.Взяв мой предыдущий пример:

На начальном этапе Page Load (Page.IsPostback == false)

<table>
  <tr>
    <td width='100'>Control index</td>
    <td width='75'>UniqueID</td>
    <td>Value</td>
  </tr>
  <tr>
    <td>0</td>
    <td>ctl00</td>
    <td>value1</td>
  </tr>
  <tr>
    <td>1</td>
    <td>ctl01</td>
    <td>value2</td>
  </tr>
  <tr>
    <td>2</td>
    <td>ctl02</td>
    <td>value3</td>
  </tr>
</table>

После постбека (Page.IsPostback == false) из какого-либо другого элемента управления, который хочет вставить элемент управления с индексом 0:

Если я сделаю Controls.AddAt(0, newControl) тогда коллекция Controls будет выглядеть примерно так:

<table>
  <tr>
    <td width='100'>Control index</td>
    <td width='75'>UniqueID</td>
    <td>Value</td>
  </tr>
  <tr>
    <td>0</td>
    <td>ctl03</td>
    <td>value0  <== the controls' unique IDs do not shift!</td>
  </tr>
  <tr>
    <td>1</td>
    <td>ctl00</td>
    <td>value1</td>
  </tr>
  <tr>
    <td>2</td>
    <td>ctl01</td>
    <td>value2</td>
  </tr>
  <tr>
    <td>3</td>
    <td>ctl02</td>
    <td>value3</td>
  </tr>
</table>

Поэтому, если бы я нажал кнопку ссылки в элементе управления со значением == value0 и UniqueID == ctl03, при обратной передаче элементы управления были бы упорядочены следующим образом, а уникальные идентификаторы не были бы в том порядке, который мне нужен.Это приведет к тому, что событие щелчка будет привязано к неправильному элементу управления:

<table>
  <tr>
    <td width='100'>Control index</td>
    <td width='75'>UniqueID</td>
    <td>Value</td>
  </tr>
  <tr>
    <td>0</td>
    <td>ctl00</td>
    <td>value0  <== the control i wanted to throw the event</td>
  </tr>
  <tr>
    <td>1</td>
    <td>ctl01</td>
    <td>value1</td>
  </tr>
  <tr>
    <td>2</td>
    <td>ctl02</td>
    <td>value2</td>
  </tr>
  <tr>
    <td>3</td>
    <td>ctl03</td>
    <td>value3  <== the actual control to which the event is attached</td>
  </tr>
</table>

Если бы мне не приходилось обрабатывать события из этих динамических элементов управления, это, вероятно, не было бы проблемой.Вот мой код:

// on init i just need to pull the records from the DB, turn them
// into a MyControl.ascx, and then add them to my panel
protected override void OnInit(EventArgs e)
{
    base.OnInit(e);

    // get my List<SomethingFromDB> ordered by value and iterate through, 
    // adding controls to the control collection
    List<SomethingFromDB> myList = remoteService.GetSomeListFromTheDB();
    foreach(SomethingFromDB something in List<SomethingFromDB>)
    {
        // load a new MyControl.ascx
        MyControl myControl = (MyControl )LoadControl("~/Controls/MyControl .ascx");
        // populate the values of myControl with the "something"
        this.populateMyControl(something);
        // dynamically add the control to my panel
        this.myPanel.Add(myControl);     
        // subscribe to event
        myControl.SomeArbitraryEvent += new EventHandler(MyArbitraryHandler);
    }

    // This event gets fired by a magical control on the page and passes a 
    // new SomethingFromDB which needs to be inserted into the DB and then 
    // dynamically inserted into the Controls collection at the specified index
    private void SomeOtherControl_ClickInsert(object sender, MyControlEventArgs e)
    {
        // insert this record into the DB             
        remoteService.InsertIntoDB(e.SomethingFromDB);     
        // dynamically load this control
        MyControl myControl = (MyControl )LoadControl("~/Controls/MyControl .ascx");
        // get the index into which we will be inserting this control
        int index = e.NewIndex;                   
        //dynamically add the control to my panel at the specified index.
        // THIS DOES NOT ADJUST THE UNIQUEID VALUES ACCORDINGLY
        // AND IS THE SOURCE OF MY PROBLEM!
        this.myPanel.AddAt(index, myControl);
    }

Пожалуйста помоги.Этот убивает меня.Если вам нужна дополнительная информация или у вас есть вопросы, дайте мне знать, и я буду рад предоставить дополнительную информацию.Я ОЧЕНЬ ценю вашу помощь!

Это было полезно?

Решение

Чтобы автоматическая нумерация работала, необходимо, чтобы элементы управления добавлялись на панель в одном и том же порядке для каждой обратной передачи.Очевидно, что при обратной передаче элементам управления должны быть назначены уникальные идентификаторы, иначе вы не получите событие элемента управления.

UniqueID инициализируется при первом использовании значением Control.ID* свойство.Если это свойство не установлено, оно автоматически генерируется как ctlxx, как вы заметили.После назначения элемент управления UniqueID доступен только для чтения.

Поэтому, если у вас есть первичный ключ той или иной формы, вы можете установить ID свойство элемента управления при его создании на основе этого первичного ключа.А UniqueID затем будет установлено это значение, когда страница загрузит свое состояние.

  • Сноска:тот UniqueID На самом деле свойство представляет собой комбинацию префикса контейнера именования и ID свойство.

Другие советы

Используйте следующий атрибут в директиве страницы.

MaintainScrollPositionOnPostback = true

Это поможет, я считаю.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top