Dynamic Gridview — обработка событий элемента управления шаблоном

Я создал собственный элемент управления gridview, который наследует gridview asp.net. Мне необходимо использовать шаблоны элементов в этом представлении сетки. Я создаю метод в своем пользовательском представлении сетки, который генерирует шаблон элемента.

public void addTemplateField(Control headerTemplateControl, Control itemTemplateControl, EventHandler bindHandler, EventHandler initHandler, string headerText, string sortExpression, bool isVisible, int? heightPx, int? widthPercent)
{
    TemplateField tField = new TemplateField();

    if (headerTemplateControl != null)
        tField.HeaderTemplate = new GridViewTemplate(ListItemType.Header, headerTemplateControl);

    if (bindHandler != null && initHandler != null)
        tField.ItemTemplate = new GridViewTemplate(ListItemType.Item, itemTemplateControl, bindHandler, initHandler);

    else if (bindHandler != null)
        tField.ItemTemplate = new GridViewTemplate(ListItemType.Item, itemTemplateControl, bindHandler, false);

    else if (initHandler != null)
        tField.ItemTemplate = new GridViewTemplate(ListItemType.Item, itemTemplateControl, initHandler, true);

    else
        tField.ItemTemplate = new GridViewTemplate(ListItemType.Item, itemTemplateControl);

    if (sortExpression != null)
        tField.SortExpression = sortExpression;

    tField.Visible = isVisible;

    if (headerText != null)
        tField.HeaderText = headerText;

    if (heightPx.HasValue)
        tField.HeaderStyle.Height = new Unit(heightPx.Value, UnitType.Pixel);

    if (widthPercent.HasValue)
        tField.HeaderStyle.Height = new Unit(widthPercent.Value, UnitType.Percentage);

    addColumnField(tField);
}

И вот как я реализовал ITemplate

public class GridViewTemplate : ITemplate
{
    int _controlCount = 0;
    ListItemType _templateType;
    EventHandler _bindHandler;
    EventHandler _initHandler;
    Control _control;
    public GridViewTemplate(ListItemType type, Control control)
    {
        this._templateType = type;
        this._control = control;
    }
    public GridViewTemplate(ListItemType type, Control control, EventHandler Handler, bool isInitHandler)
    {
        this._templateType = type;
        this._control = control;
        if (isInitHandler)
            this._initHandler = Handler;
        else
            this._bindHandler = Handler;
    }
    public GridViewTemplate(ListItemType type, Control control, EventHandler bindHandler, EventHandler initHandler)
    {
        this._templateType = type;
        this._control = control;
        this._bindHandler = bindHandler;
        this._initHandler = initHandler;
    }
    public Control Copy(Control ctrlSource)
    {
        Type _type = ctrlSource.GetType();
        Control ctrlDest = (Control)Activator.CreateInstance(_type);
        foreach (PropertyInfo prop in _type.GetProperties())
        {
            if (prop.CanWrite)
            {
                if (prop.Name == "ID")
                {
                    ctrlDest.ID = ctrlSource.ID + "_copy_" + _controlCount;
                }
                else
                {
                    prop.SetValue(ctrlDest, prop.GetValue(ctrlSource, null), null);
                }
            }
        }
        _controlCount++;

        return ctrlDest;
    }
    public void InstantiateIn(Control container)
    {
        switch (_templateType)
        {
            case ListItemType.Header:
                container.Controls.Add(_control);
                break;
            case ListItemType.Item:
                Control temp = Copy(_control);
                if(_bindHandler != null)
                    temp.DataBinding += _bindHandler;
                if (_initHandler != null)
                    temp.Init += _initHandler;
                container.Controls.Add(temp);
                break;
        }
    }

}

На странице, которая должна сказать Default.aspx.cs, я создаю это представление сетки onPreInit и присоединяю его обработчики событий onInit.

Я добавляю флажок в сетку, вызывая метод addTemplateField().

cbl = new CheckBox();
cbl.AutoPostBack = true;
init = new EventHandler(cbl_Init);
grd.addTemplateField(null, cbl, null, init, "SERVER", null, true, 20, 20);

void cbl_Init(object sender, EventArgs e)
{
    CheckBox c = (CheckBox)sender;
    c.CheckedChanged +=new EventHandler(cbl_CheckedChanged);
}

void cbl_CheckedChanged(object sender, EventArgs e)
{
  // Modify datasource
  // databind();

// если я удаляю эту привязку данных, каждый раз обрабатывается checkchanged. Если я сохраняю привязку данных, событие обрабатывается только через раз. }

Проблема заключается в том, что событие флажка checkchanged запускается попеременно. Через раз страница возвращается, но событие checkchanged не обрабатывается. Я теряюсь в поиске причины, не говоря уже о решении.!?!?!


person Aishwarya Sudhakar    schedule 22.07.2013    source источник


Ответы (1)


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

Чтобы быть более хрустальным...

  1. Страница загружается изначально с элементами управления, имеющими уникальный идентификатор,
  2. Нажмите на элемент управления, чтобы вызвать событие
  3. Сообщение страницы возвращается с элементами управления, созданными с тем же идентификатором.
  4. Нажмите на элемент управления, чтобы вызвать событие.
  5. Страница отправляет обратно, но элементы управления генерируются с другим it, который не соответствует источнику события на шаге 4.

Решение состояло в том, чтобы удалить переменную контрольного счетчика.

person Aishwarya Sudhakar    schedule 23.07.2013