Вставьте динамические элементы управления в середину коллекции элементов управления - PullRequest
5 голосов
/ 20 февраля 2009

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

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

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

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

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

<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);
    }

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

Ответы [ 2 ]

5 голосов
/ 20 февраля 2009

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

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

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

  • Сноска: свойство UniqueID фактически является комбинацией префикса контейнера именования и свойства ID.
0 голосов
/ 05 октября 2010

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

MaintainScrollPositionOnPostback = true

Полагаю, это поможет.

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