Как создать условный контент в повторителе с привязкой к данным - PullRequest
4 голосов
/ 08 ноября 2008

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

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

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

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

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

Есть идеи, как сделать это возможным?

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

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

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

<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>

Ответы [ 2 ]

4 голосов
/ 10 ноября 2008

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

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

Первое - это использование события, созданного элементом 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. В моем конкретном сценарии я мог сделать этот тип одним элементом управления с помощью ID. Это может быть легко изменено при необходимости.

 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);
      }
   }
1 голос
/ 08 ноября 2008

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

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

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

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