Pull to refresh

ASP.NET 4.0: обзор ClientID

Reading time 10 min
Views 3.8K
Original author: ASP QA Team

Вступление


Одним из нововведений в четвертой версии ASP.NET стала возможность контролировать формирование идентификаторов элементов разметки на клиенте. Ранее фреймворк задавал уникальный идентификатор для каждого элемента. Это приводило к тому, что определяемые вами идентификаторы преображались во что-то похожее на это: ctl00_MasterPageBody_ctl01_Textbox1.

Проблема


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

Решение в старом стиле


Если вы работали с ASP.NET достаточное время, то знаете, как решать описанную проблему. Каждый элемент управления содержит свойство только для чтения ClientID, которое определяет клиентский идентификатор для этого элемента. Вы можете использовать это свойство в своем серверном коде при динамическом добавлении скриптов или, в более распространенном случае, использовать его в коде разметки (стиль старого ASP) для реализации скриптов на стороне клиента.
<script type="text/javascript">
  function DoSomething(){
    alert('<%= Control.ClientID %>');
  }
</script>


* This source code was highlighted with Source Code Highlighter.


Решение в ASP.NET 4.0


Первым делом, позвольте мне объяснить, почему мы решили заняться этой проблемой в четвертой версии фреймворка. Реализация поддержки уникальности идентификаторов на стороне клиента с ростом скриптов приводила к тому, что код содержал все больше ухищрений. С такой системой не существовало нормального пути для реализации работы множества элементов управления с большим количеством внешних файлов скриптов. Кроме того, должен был бы существовать какой-нибудь механизм для разработчика контролировать эту систему назначения уникальных идентификаторов. Разработчики любят все контролировать, нужно им это или нет, такова наша природа :). Решение, которое мы предлагаем, содержит четыре режима, которые разработчик может использовать для полного контроля над системой идентификаторов. Свойство ID элементов управления модифицируется исходя из установленного режима ClientIDMode, и, соответственно, формирует идентификатор на стороне клиента.

Режимы и что они делают


Для каждого элемента управления (включая Page и MasterPage ) добавлено новое свойство, названное ClientIDMode, которое используется для выбора механизма формирования клиентского ID.
<asp:Label ID="Label1" runat="server" ClientIDMode="[Mode Type]" />

* This source code was highlighted with Source Code Highlighter.


Режимы
  • Legacy (устаревший): режим по умолчанию, когда ClientIDMode не установлен нигде в дереве элементов управления. Этот режим идентичен тому, как формировался идентификатор в версии 2.0 фреймворка (как и в 3.0 и 3.5). Этот режим будет генерировать ID похожие на ctl00_MasterPageBody_ctl01_Textbox1.
  • Inherit (наследуемый): этот режим по умолчанию для любого элемента управления. В этом случае для получения режима используется значение ClientIDMode у родительского элемента. Вам не нужно устанавливать это свойство для каждого элемента управления, поскольку оно установлено по умолчанию, использовать его можно в случае, если необходимо изменить механизм для элемента с какого-то режима на режим присущий родительскому.
  • Static (статический): этот режим делает именно то, о чем вы подумали, он задает статический ID. Это означает, что то что вы укажите для ID элемента управления, то и будет использовано для идентификатора на стороне клиента. Внимание, это означает, что в случае если статический ClientIDMode используется в элементе управления с повторяющимися элементами, то разработчик несет ответственность за самостоятельное обеспечение уникальности идентификаторов на стороне клиента.
  • Predictable (предсказуемый): этот режим используется, когда требуется обеспечить уникальность, но сделать это предсказуемо. Наиболее распространенным примером для использования этого режима могут стать элементы управления с привязкой к источникам данных. В этом случае, Фреймворк пройдет всю иерархию элементов управления, присвоив каждому элементу (кроме статических элементов) префикс в виде ID родительского элемента. В случае, когда элемент управления расположен внутри элемента управления с привязкой к данным, к ID добавится суффикс в виде некоторых значений. Для управления этими значениями используется свойство ClientIDRowSuffix (смотрите примеры). Этот режим будет генерировать значения идентификаторов похожих на Gridview1_Label1_0.


Примеры


Legacy-режим


Legacy-режим генерирует ID на клиентской стороне так же, как это делал фреймворк с версии 2.0.

разметка:
<asp :TextBox ID ="txtEcho" runat ="server" Width ="65%" ClientIDMode ="Legacy" />

* This source code was highlighted with Source Code Highlighter.


результат:
<input id="ctl00_MasterPageBody_ctl00_txtEcho" style="width: 65%"
name="ctl00$MasterPageBody$ctl00$txtEcho" />


* This source code was highlighted with Source Code Highlighter.


Static-режим


Статический режим наиболее простой из всех режимов ClientIDMode, который позволяет вам получить ID на клиентской стороне таким же какой ID был задан для серверного элемента управления. Снова требуется предупредить, что в случае если статический ClientIDMode используется в элементе управления с повторяющимися элементами, то ответственность на формирование уникальности идентификаторов на стороне клиента ложится на разработчика.

разметка:
<asp:TextBox ID="txtEcho2" runat="server" Width="65%" ClientIDMode="Static" />

* This source code was highlighted with Source Code Highlighter.


результат:
<input id="txtEcho2" style="width: 65%" name="ctl00$MasterPageBody$ctl00$txtEcho2" />

* This source code was highlighted with Source Code Highlighter.


Predictable-режим


Предсказуемый режим бьет прямо в сердце проблемы. Ранее фреймворк генерировал уникальные ID, чтобы избежать совпадения идентификаторов, например в самом распространенном случае — внутри элементов управления с привязкой к источникам данных. Хотя предсказуемый режим разработан именно для таких моментов, он может быть использован и в других случаях. Для использования предсказуемого режима есть три варианта, каждый из которых указывается через свойство ClientIDRowSuffix, которое указывает какой суффикс использовать для каждого элемента. ClientIDRowSuffix использует значения из коллекции ключевых полей элемента управления, так что если элемент управления не содержит такой коллекции, то это свойство не будет работать. В случае если это свойство не установлено или не доступно, то для суффикса будет использовано числовое значение индекса элемента.

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

разметка:
<asp:GridView ID="EmployeesNoSuffix" runat="server" AutoGenerateColumns="false"
ClientIDMode="Predictable" >
  <Columns>
    <asp:TemplateField HeaderText="ID">
      <ItemTemplate>
        <asp:Label ID="EmployeeID" runat="server" Text='<%# Eval("ID") %>' />
      </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField HeaderText="Name">
      <ItemTemplate>
        <asp:Label ID="EmployeeName" runat="server" Text='<%# Eval("Name") %>' />
      </ItemTemplate>
    </asp:TemplateField>
  </Columns>
</asp:GridView>


* This source code was highlighted with Source Code Highlighter.


результат:
<table id="EmployeesNoSuffix" style="border-collapse: collapse" cellspacing="0" rules="all" border="1">
  <tbody>
    <tr>
      <th scope="col">ID</th>
      <th scope="col">Name</th>
    </tr>
    <tr>
      <td><span id="EmployeesNoSuffix_EmployeeID_0">1</span></td>
      <td><span id="EmployeesNoSuffix_EmployeeName_0">EmployeeName1</span></td>
    </tr>
    ...
    <tr>
      <td><span id="EmployeesNoSuffix_EmployeeID_8">9</span></td>
      <td><span id="EmployeesNoSuffix_EmployeeName_8">EmployeeName9</span></td>
    </tr>
  </tbody>
</table>


* This source code was highlighted with Source Code Highlighter.


2. ClientIDRowSuffix указан, в этом случае производится поиск значений ключевых полей для значений суффиксов.
разметка:
<asp:GridView ID="EmployeesSuffix" runat="server" AutoGenerateColumns="false"
ClientIDMode="Predictable" ClientIDRowSuffix="ID" >
  <Columns>
    <asp:TemplateField HeaderText="ID">
      <ItemTemplate>
        <asp:Label ID="EmployeeID" runat="server" Text='<%# Eval("ID") %>' />
      </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField HeaderText="Name">
      <ItemTemplate>
        <asp:Label ID="EmployeeName" runat="server" Text='<%# Eval("Name") %>' />
      </ItemTemplate>
    </asp:TemplateField>
  </Columns>
</asp:GridView>


* This source code was highlighted with Source Code Highlighter.


результат:
<table id="EmployeesSuffix" style="border-collapse: collapse" cellspacing="0" rules="all" border="1">
  <tbody>
    <tr>
      <th scope="col">ID</th>
      <th scope="col">Name</th>
    </tr>
    <tr>
      <td><span id="EmployeesSuffix_EmployeeID_1">1</span></td>
      <td><span id="EmployeesSuffix_EmployeeName_1">EmployeeName1</span></td>
    </tr>
    ...
    <tr>
      <td><span id="EmployeesSuffix_EmployeeID_9">9</span></td>
      <td><span id="EmployeesSuffix_EmployeeName_9">EmployeeName9</span></td>
    </tr>
  </tbody>
</table>


* This source code was highlighted with Source Code Highlighter.


3. ClientIDRowSuffix указано, но вместо одного значения задано несколько. Приводит к тому, что суффикс будет состоять из нескольких значений.
разметка:
<asp:GridView ID="EmployeesCompSuffix" runat="server" AutoGenerateColumns="false"
ClientIDMode="Predictable" ClientIDRowSuffix="ID, Name" >
  <Columns>
    <asp:TemplateField HeaderText="ID">
      <ItemTemplate>
        <asp:Label ID="EmployeeID" runat="server" Text='<%# Eval("ID") %>' />
      </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField HeaderText="Name">
      <ItemTemplate>
        <asp:Label ID="EmployeeName" runat="server" Text='<%# Eval("Name") %>' />
      </ItemTemplate>
    </asp:TemplateField>
  </Columns>
</asp:GridView>


* This source code was highlighted with Source Code Highlighter.


результат:
<table id="EmployeesCompSuffix" style="border-collapse: collapse" cellspacing="0" rules="all" border="1">
  <tbody>
    <tr>
      <th scope="col">ID</th>
      <th scope="col">Name</th>
    </tr>
    <tr>
      <td><span id="EmployeesCompSuffix_EmployeeID_1_EmployeeName1">1</span></td>
      <td><span id="EmployeesCompSuffix_EmployeeName_1_EmployeeName1">EmployeeName1</span></td>
    </tr>
    ...
    <tr>
      <td><span id="EmployeesCompSuffix_EmployeeID_9_EmployeeName9">9</span></td>
      <td><span id="EmployeesCompSuffix_EmployeeName_9_EmployeeName9">EmployeeName9</span></td>
    </tr>
  </tbody>
</table>


* This source code was highlighted with Source Code Highlighter.


Заключение


Возможность полностью контролировать генерацию идентификаторов на клиентской стороне — это возможность, которую хотел каждый. Мы уверены, что нашли хорошее решение и думаем, что оно добавит разработчикам тот необходимый функционал, который нужен для создания большого объема клиентского кода. Предварительная версия доступна на этом CTP, которое было представлено на PDC 2008. Для большего количества информации и более детального описания прочитаете этот пост Scott Galloway.
Tags:
Hubs:
+20
Comments 9
Comments Comments 9

Articles