Как создать условный контент в репитере привязки данных

Я настраиваю пользовательский элемент управления, управляемый конфигурацией XML. Это проще объяснить на примере. Взгляните на следующий фрагмент конфигурации:

<node>
  <text lbl = "Text:"/>
  <checkbox lbl = "Check me:" checked = "true"/>
</node>

Я пытаюсь перевести этот фрагмент в одно текстовое поле и элемент управления флажком. Конечно, если бы фрагмент содержал больше узлов, автоматически создавалось бы больше элементов управления.

Учитывая итеративный характер задачи, я решил использовать Repeater. В нем я разместил два (а точнее, больше, см. Ниже) Controls, одно CheckBox и одно Editbox. Чтобы выбрать, какой элемент управления будет активирован, я использовал команду встроенного переключателя, проверив имя текущего узла конфигурации.

К сожалению, это не работает. Проблема заключается в том, что переключатель запускается во время рендеринга, спустя много времени после того, как произошло связывание данных. Одно это не было бы проблемой, не потому, что узел конфигурации мог предложить необходимую информацию для привязки данных. Подумайте, что произойдет, если элемент управления флажком попытается привязаться к текстовому узлу в приведенном выше фрагменте, отчаянно ища его атрибут "checked".

Есть идеи, как это сделать?

Спасибо, Вооз

Вот мой текущий код:

Вот мой код (который работает с более сложным синтаксисом, чем приведенный выше):

<asp:Repeater ID = "settingRepeater" runat = "server">
        <ItemTemplate>
           <% 
              switch (((XmlNode)Page.GetDataItem()).LocalName)
              {
                 case "text":
           %>
           <asp:Label ID = "settingsLabel" CssClass = "editlabel" Text='<%# XPath("@lbl") %>' runat = "server" />
           <asp:TextBox ID = "settingsLabelText" Text='<%# SettingsNode.SelectSingleNode(XPath("@xpath").ToString()).InnerText %>'
              runat = "server" AutoPostBack = "true"  Columns='<%#  XmlUtils.OptReadInt((XmlNode)Page.GetDataItem(),"@width",20) %>'
              />
           <% break;
                 case "checkbox":
           %>
           <asp:CheckBox ID = "settingsCheckBox" Text='<%# XPath("@lbl") %>' runat = "server"
                         Checked='<%# ((XmlElement)SettingsNode.SelectSingleNode(XPath("@xpath").ToString())).HasAttribute(XPath("@att").ToString()) %>'
            />
          <% break;
              } %>
           &nbsp;&nbsp;
        </ItemTemplate>
     </asp:Repeater>
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
7 872
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужно что-то похожее на это:

<ItemTemplate>
    <%# GetContent(Page.GetDataItem()) %>
</ItemTemplate>

А затем создайте все ваши элементы управления в коде программной части.

Ответ принят как подходящий

Спустя один уик-энд вот что я пришел с решением. Моя главная цель состояла в том, чтобы найти что-то, что одновременно будет работать и позволит вам указывать точное содержимое шаблона элемента в разметке. Выполнение чего-либо из кода будет работать, но все же может быть громоздким.

Код должен быть простым, но суть состоит в двух частях.

Первый - это использование события создания элемента Repeater для фильтрации нежелательных частей шаблона.

Второй - хранить решения, принятые во ViewState, чтобы воссоздать страницу во время обратной публикации. Последнее имеет решающее значение, поскольку вы заметите, что я использовал Item.DataItem. Во время обратной публикации управление воспроизведением происходит намного раньше в жизненном цикле страницы. Когда срабатывает ItemCreate, DataItem имеет значение NULL.

Вот мое решение:

Разметка управления

 <asp:Repeater ID = "settingRepeater" runat = "server" 
            onitemcreated = "settingRepeater_ItemCreated" 
          >
        <ItemTemplate>
             <asp:PlaceHolder  ID = "text" runat = "server">
                  <asp:Label ID = "settingsLabel" CssClass = "editlabel" Text='<%# XPath("@lbl") %>' runat = "server" />
                  <asp:TextBox ID = "settingsLabelText"  runat = "server"
                      Text='<%# SettingsNode.SelectSingleNode(XPath("@xpath").ToString()).InnerText %>'
                     Columns='<%#  XmlUtils.OptReadInt((XmlNode)Page.GetDataItem(),"@width",20) %>'

                   />

            </asp:PlaceHolder>
            <asp:PlaceHolder ID = "att_adder" runat = "server">
               <asp:CheckBox ID = "settingsAttAdder" Text='<%# XPath("@lbl") %>' runat = "server"
                             Checked='<%# ((XmlElement)SettingsNode.SelectSingleNode(XPath("@xpath").ToString())).HasAttribute(XPath("@att").ToString()) %>'
                />
            </asp:PlaceHolder>
      </ItemTemplate>
  </asp:Repeater>

Примечание: для большей простоты я добавил элемент управления PlaceHolder, чтобы сгруппировать элементы и решить, какие элементы управления легче удалить.

Код позади

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

 protected List<string> repeaterItemTypes
   {
      get
      {
         List<string> ret = (List<string>)ViewState["repeaterItemTypes"];
         if (ret == null)
         {
            ret = new List<string>();
            ViewState["repeaterItemTypes"] = ret;
         }
         return ret;
      }
   }

   protected void settingRepeater_ItemCreated(object sender, RepeaterItemEventArgs e)
   {
      string type;
      if (e.Item.DataItem != null)
      {
         // data binding mode..
         type = ((XmlNode)e.Item.DataItem).LocalName;
         int i = e.Item.ItemIndex;
         if (i == repeaterItemTypes.Count)
            repeaterItemTypes.Add(type);
         else
            repeaterItemTypes.Insert(e.Item.ItemIndex, type);
      }
      else
      {
         // restoring from ViewState
         type = repeaterItemTypes[e.Item.ItemIndex];
      }

      for (int i = e.Item.Controls.Count - 1; i >= 0; i--)
      {
         if (e.Item.Controls[i].ID != type) e.Item.Controls.RemoveAt(i);
      }
   }

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