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, създавам този gridview 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();

// ако премахна този databind, checkchanged се обработва всеки път. Ако запазя databind, събитието се обработва само алтернативно. }

Проблемът е, че събитието за промяна на квадратчето за отметка се задейства за алтернативно време. Всеки друг път публикацията на страницата се връща, но събитието 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