В настоящее время я являюсь информационным архитектором и разработчиком JavaScript по профессии, но в последнее время я снова возвращаюсь к внутреннему кодированию. И, пытаясь интегрировать прототип HTML и работать с нашей CMS на основе C#, я вступил в драку с нашими программистами из-за того, что атрибуты HTML ID произвольно переписываются .NET для элементов формы.
Я могу понять аргументацию кода программной части для изменения идентификаторов .NET, но тот факт, что вы больше не можете использовать идентификаторы при попытке разработки, например. Улучшенные интерфейсы jQuery вызывают некоторые трения. Что я могу сделать, чтобы обойти это?
Я пробовал использовать вместо этого атрибут class, но это действительно дерьмо, не то, для чего он предназначен, и не может решить эту проблему, когда .NET эффективно меняет визуализированный источник на лету. Это также означает, что CSS сейчас менее полезен и его менее эффективно создавать и поддерживать.
Любые советы и рекомендации очень ценны - что-нибудь для нескольких бессонных ночей меньше ...





Вы можете расширить элементы управления .net и заставить их возвращать фактические идентификаторы при вызове связанных свойств.
ClientID - это атрибут id, а UniqueID - атрибут name элементов html. Поэтому, когда вы создаете текстовое поле, подобное приведенному ниже, и используете его вместо текстового поля в framework, вы делаете рендеринг атрибутов id и name так же, как идентификатор на стороне сервера.
public class MyTextBox : TextBox
{
public override string ClientID { get { return ID; } }
public override string UniqueID { get { return ID; } }
}
Чтобы использовать этот новый пользовательский элемент управления, в основном зарегистрируйте этот элемент управления, как и для пользовательского элемента управления (вы можете сделать это в web.config, поэтому вам не придется делать это на всех своих страницах):
<%@ Register Assembly = "MyLibrary" NameSpace = "MyLibrary.WebControls" TagPrefix = "MyPrefix" %>
И используйте его, как текстовое поле:
<MyPrefix:MyTextBox ID = "sampleTextBox" runat = "server" />
Короткий ответ - нет, с веб-формами идентификатор всегда можно переписать в зависимости от вложенности элемента. Вы можете получить доступ к идентификатору через свойство ClientID, чтобы вы могли установить идентификаторы в переменные в скрипте в конце страницы / элемента управления, а затем поместить их в jQuery.
что-то вроде этого:
<asp:button id = "ImAButton" runat = "server">Click Me</asp:button>
<script type = "text/javascript">
var buttonId = "<%=ImAButton.ClientId%>";
$("#"+buttonId).bind('click', function() { alert('hi); });
</script>
Я знаю, что это хитрость, но она сработает. (Я должен отметить, что для не инициированных, я использую метод Prototype $ get by id)
Конечно, вам понадобятся кавычки вокруг этого тега сервера. И я не понимаю, почему это взлом. Это законный метод, который я использую все время. Вот для чего нужны такие вещи, как серверные теги и ClientID.
Я думаю, это просто похоже на взлом, потому что это грязно. Я бы предпочел, чтобы они были статическим, предсказуемым идентификатором элемента управления, с которым может разговаривать javascript.
Я тоже все время использую этот подход. Я обычно объявляю все свои «динамические» переменные в теге заголовка (на автономных страницах) или в элементе управления asp: Content, который записывает в asp: ContentPlaceHolder в теге заголовка мастера. Это, по крайней мере, сохраняет все переменные, содержащие динамические идентификаторы, в одном месте.
Гленн, я добавил кавычки в литерал buttonId и знак «#» в селектор jquery к вашему ответу, чтобы он был на 100% правильным :).
Один из способов - переопределить идентификатор вручную:
public override string UniqueID
{
get { return this.ID; }
}
public override string ClientID
{
get { return this.ID; }
}
Рик Страл написал сообщение в блоге с дополнительной информацией об этом подходе.
Взгляните на ASP.Net MVC - он обращается к иерархиям объектов чрезмерного уничтожения, которые ASP.Net генерирует по умолчанию.
Этот сайт написан на MVC (я думаю) - посмотрите на его структуру. Если бы я сейчас работал над новым проектом, я бы сначала рассмотрел его
Если вы застряли на базовом ASP.Net, будьте осторожны, переопределяя ClientID и UniqueID - это имеет тенденцию нарушать многие веб-элементы управления.
Лучший способ, который я нашел, - передать нечитаемый ClientID в Javascript.
Лично я использую набор методов, которые я разработал для преодоления "магии" ASP.NET на стороне сервера (я еще не использовал материал MS MVC) и моего кода на стороне клиента из-за того, что происходит изменение идентификаторов. . Вот только один, который может оказаться полезным, а может и не оказаться:
public void RegisterControlClientID(Control control)
{
string variableDeclaration = string.Format("var {0} = \"{1}\";", control.ID, control.ClientID);
ClientScript.RegisterClientScriptBlock(GetType(), control.ID, variableDeclaration, true);
}
Итак, в коде на стороне сервера вы просто вызываете this и передаете экземпляр элемента управления, для которого вы хотите использовать более удобное имя. Другими словами, во время время разработки у вас может быть текстовое поле с идентификатором «m_SomeTextBox», и вы хотите иметь возможность писать свой JavaScript с тем же именем - вы просто вызываете этот метод в своем коде на стороне сервера:
RegisterControlClientID(m_SomeTextBox);
Затем на клиенте отображается следующее:
var m_SomeTextBox = "ctl00_m_ContentPlaceHolder_m_SomeTextBox";
Таким образом, весь ваш код JavaScript может совершенно не знать, какое имя ASP.NET решает назвать переменной. Конечно, здесь есть некоторые предостережения, например, когда у вас есть несколько экземпляров элемента управления на странице (например, из-за использования нескольких экземпляров пользовательских элементов управления, каждый из которых имеет экземпляр m_SomeTextBox), но обычно этот метод может быть полезным для ваших самых элементарных нужд.
Обычно я создаю общую функцию, которая получает имя поля. Он добавляет обычный префикс «asp.net» и возвращает объект.
var elemPrefix = 'ctl00-ContentPlaceHolder-'; //replace the dashes for underscores
var o = function(name)
{
return document.getElementById(elemPrefix + name)
}
При этом вы можете использовать такие вызовы в jQuery.
$(o('buttonId')).bind('click', function() { alert('hi); });
Если вы используете jQuery, то в вашем распоряжении множество Селекторы CSS и специальные селекторы jQuery для таргетинга на элементы на вашей странице. Поэтому вместо того, чтобы выбирать кнопку отправки по ее идентификатору, вы можете сделать что-то вроде:
$('fieldset > input[type = "submit"]').click(function() {...});
Вы определенно не хотите жестко закодировать идентификатор, сгенерированный asp.net, в свой CSS, потому что он может измениться, если вы переставите элементы на своей странице таким образом, что изменится дерево управления.
Вы правы, что идентификаторы CSS имеют свое место, поэтому я бы проигнорировал предложения просто использовать классы.
Описанные здесь различные хаки javascript - излишки для небольшой проблемы. Таким образом, происходит наследование от класса и переопределение свойства ID. И, конечно, бесполезно предлагать переключиться на MVC, когда все, что вам нужно, - это рефакторинг некоторого CSS.
Просто имейте отдельные блоки div и span, на которые вы нацеливаетесь с помощью CSS. Не настраивайте элементы управления ASP.NET напрямую, если хотите использовать идентификаторы.
<div id = "DataGridContainer">
<asp:datagrid runat=server id = "DataGrid" >
......
<asp:datagrid>
</div>
Я вижу, что система .NET кажется менее интуитивно понятной, но дайте ей шанс. По моему опыту, на самом деле это приводит к созданию более чистого кода. Конечно
<asp:button id = "ImAButton" runat = "server">Click Me</asp:button>
<script type = "text/javascript">
var buttonId = <%=ImAButton.ClientId%>
$(buttonId).bind('click', function() { alert('hi); });
</script>
работает отлично. Но он страдает отсутствием модульности. На самом деле вам нужно что-то вроде этого:
<script type = "text/javascript">
function MakeAClick(inid)
{
$(inid).bind('click', function() { alert('hi); });
}
</script>
а затем позже с вашим кодом на стороне java или на стороне C# вы вызываете MakeAClick. Конечно, на стороне C# это имеет больше смысла, там вы просто ClientID.
Возможно, это настоящая проблема с кодом, который вы просматриваете.
Гораздо лучшим подходом было бы использовать ClientIDMode и установить его на static. Вы даже можете установить его для конкретной страницы или глобально в файле web.config. Тогда вам больше не придется сталкиваться с этой проблемой, и ваш JQuery станет намного чище.
Верх страницы:
<%@ Page Title = "" ClientIDMode = "Static" Language = "C#" CodeBehind = "..." Inherits = "WebApplication1.WebForm2" %>
Только на контроле:
<asp:Panel runat = "server" ClientIDMode = "Static"></asp:Panel>
Вам также понадобятся адаптеры для элементов управления списком и файл .browser.