Расширение функциональности Web контроллеров. Часть 1

Тема в разделе ".NET", создана пользователем NikSoft, 31 дек 2006.

  1. NikSoft

    NikSoft Гость

    Репутация:
    0
    Пусть мы имеем DataGrid Web контроллер на aspx странице, как показано на рисунке.

    Расширение функциональности Web контроллеров. Часть 1

    Каждая строка содержит Auto CheckBox, Price TextBox Web контроллеры. Если Auto установлен, то ввод информации в Price запрешен, иначе разрешен. Эта задача решается легко на сервере с помощью события OnCheckedChanged. Но при этом aspx страница перезагружается. Чтобы решить эту проблему на клиенте добавим Java script к Auto CheckBox Web контроллеру.
    Создадим новый проект в Visual Studio 2005 типа Class Library с именем CheckBoxNik. Добавим новый тип CheckBoxNik.CheckBox, который наследует из System.Web.UI.WebCotrols.CheckBox, как видно из следующего кода.

    Код (Text):
    using System;

    namespace CheckBoxNik
    {
    public class CheckBox: System.Web.UI.WebControls.CheckBox
    {
    string _targetControlID;
    const string _addAttribute = "onClick(this, '{0}');";


    #region Properties
    public string TargetControlID
    {
    get
    {
    return _targetControlID;
    }
    set
    {
    _targetControlID = value;  
    }
    }
    #endregion

    #region Members overrides
    protected override void AddAttributesToRender(System.Web.UI.HtmlTextWriter writer)
    {

    writer.AddAttribute("onClick", String.Format(_addAttribute, TargetControlID));

    base.AddAttributesToRender(writer);
    }

    protected override void OnPreRender(EventArgs e)
    {
    Page.ClientScript.RegisterClientScriptInclude("CheckBoxNik", Page.ClientScript.GetWebResourceUrl(this.GetType(), "CheckBoxNik.JavaScript.js"));

    base.OnPreRender(e);
    }
    #endregion

    }
    }
    Тип имеет приватное поле – _targetControlID для хранения идентификатора Price контроллера, доступ к которому обеспичивает свойство TargetControlID. Кроме того, добавлены 2 метода AddAttributesToRender, OnPreRender. Первый метод добавляет атрибут ( Java script ) к HTML тэгу “input”, как показано на рисунке.

    Расширение функциональности Web контроллеров. Часть 1

    Данный атрибут содержит вызов функции onClick, когда мы устанавливаем или сбрасываем Auto Web контроллер. Реализация функции onClick дана в файле JavaScript.js который надо добавить к проекту ( смотри нижеследующий рисунок ).

    Расширение функциональности Web контроллеров. Часть 1

    Свойство Build Action устанавливаем к Embedded Recource ( обведено синим овалом ). Это позволяет поместить исходный текст функции onClick в ассамблею CheckBoxNik.dll, получающуся в результате построения решения( Build Solution ) данного проекта. Далее помещаем CheckBoxNik.dll в директорию Bin сайта.
    Данный Java script будет кэширован браузером при первой загрузке aspx страницы, что сокращает время загрузки последующих вызовов страницы. Функция onClick имеет 2 параметра. В первом передается обьект Auto, в втором - идентификатор Web контроллера Price. Клиентский идентификатор Web контроллера, помещенного в DataGrid, формируется из 3 частей: идентификатора DataGrid Web контроллера, номера строки, в которой находится контроллер, идентификатора самого контроллера. Все три части разделены символом подчеркивания, как например, ItemsGrid_ctl02_AutoCheckBoxID. Зная это, функция onClick вычисляет клиентский идентификатор Web контроллера Price, после чего находим обьект Price. Устанавливаем свойство disabled этого обьекта в зависимости от значения обьекта Auto. Идентификатор Web контроллера Price передается в функцию onClick с помощью свойства TargetControlID, значение которого устанавливается в Auto CheckBox Web контроллере ( смотри нижеследующий код ).

    Код (Text):
    <datasoft:CheckBox ID="AutoCheckBoxID" TargetControlID="PriceTextBoxID" runat="server" AutoPostBack=false Checked='<%# DataBinder.Eval(Container.DataItem,"auto")%>'/>
    Данный контроллер необходимо зарегестрировать в начале aspx страницы ( смотри нижеследующий код ).

    Код (Text):
    <%@ Register Assembly="CheckBoxNik" Namespace="CheckBoxNik" TagPrefix="datasoft" %>
    В второй части статьи я покажу как осуществить доступ к ассамблее CheckBoxNik.dll посредством URL.
     
  2. Dr.Gigabit

    Dr.Gigabit Гость

    Репутация:
    0
    Как насчет генерации JScript кода из C# ? Позволяет практически избавиться от скриптов а программировать подобную логику на более-меннее нормальном языке :blink:
     
  3. Pasha

    Pasha Гость

    Репутация:
    0
    2 Dr.Gigabit: Автор, судя по всему, именно про это и пытается рассказать. Про то, как найти в DOM объекты, соответствующие серверным контролам. И про то, как привязать к ним скриптовые обработчики событий.

    Немного непонятно, почему Control переведен как контроллер.
    <!--QuoteBegin-NikSoft+31:12:2006, 07:45 -->
    <span class="vbquote">(NikSoft @ 31:12:2006, 07:45 )</span><!--QuoteEBegin-->Клиентский идентификатор Web контроллера, помещенного в DataGrid, формируется из 3 частей: идентификатора DataGrid Web контроллера, номера строки, в которой находится контроллер, идентификатора самого контроллера. Все три части разделены символом подчеркивания, как например, ItemsGrid_ctl02_AutoCheckBoxID. Зная это, функция onClick вычисляет клиентский идентификатор Web контроллера Price, после чего находим обьект Price.
    [snapback]52144" rel="nofollow" target="_blank[/snapback]​
    [/quote]
    По теме: а если грид, будет лежать не просто на странице, а внутри, скажем, PlaceHolder-а (или любого другого контрола с интерфейсом INamingContainer)? ClientID у чекбокса не поменяется? И не слишком ли это смело - считать, что механизим генерации "клиентского идентификатора Web контроллера Price" останется тем же в, скажем, .net 4.0.
     
  4. Dr.Gigabit

    Dr.Gigabit Гость

    Репутация:
    0
    Я несколько не то имел ввиду под генерацией...В примере получается что-то вроде обратного, т.е. привазяка jscript-C# обработчики.

    Что касается ClientID -- внутри AjaxControl Toolkint такой же финт ушами делается, причем от хардкондых айдишников в глазах рябит. По опыту -- при переходе от 1.1 к 2.0 были проблемы с подобным трюком :)
     
  5. karlito

    karlito Гость

    Репутация:
    0
    Для: NikSoft
    Код (Text):
    Page.ClientScript.RegisterClientScriptInclude("CheckBoxNik", Page.ClientScript.GetWebResourceUrl(this.GetType(), "CheckBoxNik.JavaScript.js"));
    Не слишком ли тяжело таскть с собой скриптовый файл?

    Мы бУдИм вас убИвать... ХА-ха-ХА...

    Для: Dr.Gigabit
    убИвать... ХА-ха-ХА...

    Ничо не понял. обработчики всё равно остаются клиентские, JavaStript-овые.

    Для: Pasha
    Поддерживаю.

    Как только страница переходит на поддержку ATLAS Beta 1. Пиши-пропало. Не продашь ты NikSoft свой контрол - работать не будет. Надеюсь, до релиза atlas починят. А пока перуэты в воздухе с тройным подвыпедвертом - на GET запросе регистрируешь скрипт с помощью стандартного ClientScriptManager-а, а на POST регистрируешь этот скрипт с помощь атласовского ClientScriptManager-а. Жаль примера под рукой нет.
     
  6. Pasha

    Pasha Гость

    Репутация:
    0
    <!--QuoteBegin-karlito+10:01:2007, 00:41 -->
    <span class="vbquote">(karlito @ 10:01:2007, 00:41 )</span><!--QuoteEBegin-->Не слишком ли тяжело таскть с собой скриптовый файл?
    [snapback]52658" rel="nofollow" target="_blank[/snapback]​
    [/quote]
    Нет, вполне обычная практика. Очень хорошо решает проблемы с подключением кучи скриптов. Тот же atlas так делает....

    <!--QuoteBegin-karlito+10:01:2007, 00:41 -->
    <span class="vbquote">(karlito @ 10:01:2007, 00:41 )</span><!--QuoteEBegin-->Как только страница переходит на поддержку ATLAS Beta 1. Пиши-пропало. Не продашь ты NikSoft свой контрол - работать не будет. Надеюсь, до релиза atlas починят. А пока перуэты в воздухе с тройным подвыпедвертом - на GET запросе регистрируешь скрипт с помощью стандартного ClientScriptManager-а, а на POST регистрируешь этот скрипт с помощь атласовского ClientScriptManager-а. Жаль примера под рукой нет.
    [snapback]52658" rel="nofollow" target="_blank[/snapback]​
    [/quote]
    Это они вроде почти вылечили в atlas beta2/rc1. По крайней мере, теперь глюки не так часто проявляются.

    IMHO, статью следовало бы переименовать в что-то вроде "как связать код JavaScript и серверные элементы управления ASP.NET".
     
  7. Pasha

    Pasha Гость

    Репутация:
    0
    Для: NikSoft
    пример (не очень аккуратный, нарисован только для демонстрации)
    Код (Text):
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
    <title>Sample Page</title>
    </head>
    <body>
    <form id="form1" runat="server">
    <div>
    <asp:DataGrid ID="TestGrid" runat="server" AutoGenerateColumns="false" ShowHeader="false" OnItemDataBound="TestGrid_ItemDataBound">
    <Columns>
    <asp:TemplateColumn>
    <ItemTemplate>
    <asp:TextBox ID="textBoxToTarget" runat="server" />
    </ItemTemplate>
    </asp:TemplateColumn>
    <asp:TemplateColumn>
    <ItemTemplate>
    <asp:Button ID="buttonToAttachScript" runat="server" Text="Click Me" />
    </ItemTemplate>
    </asp:TemplateColumn>
    </Columns>
    </asp:DataGrid>
    </div>
    </form>
    </body>
    </html>
    Код (Text):
    // usings here
    public partial class _Default : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    TestGrid.DataSource = new int[5];
    TestGrid.DataBind();
    }
    }

    private string scriptTemplate = "document.getElementById('{0}').value = 'blah-blah-blah'; return false;";
    protected void TestGrid_ItemDataBound(object sender, DataGridItemEventArgs e)
    {
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
    Control textBoxControl = e.Item.Cells[0].FindControl("textBoxToTarget");
    Button button = (Button)e.Item.Cells[1].FindControl("buttonToAttachScript");
    button.OnClientClick = String.Format(scriptTemplate, textBoxControl.ClientID);
    }
    }
    }
     
Загрузка...

Поделиться этой страницей