我创建了一个自定义的gridview控件,它继承了asp.net gridview。我需要在此网格视图中使用项目模板。我在自定义网格视图中创建了一个方法来生成项目模板。
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的页面中,我在PreInit上创建了这个网格视图,并将其事件处理程序附加到Init上。
我通过调用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事件。我找不到原因,更不用说解决办法了。!?!?!
我找到了问题的根本原因。它在gridviewtemplate类的Copy方法中。问题是,对于每次回发,生成的控件都是在一个唯一的id中完成的。因此,在回发时,控件触发的事件更改了其id,因此没有触发任何事件。
要变得更水晶。。。
- 页面最初加载具有唯一id的控件
- 单击控件以触发事件
- 页面回发了使用相同id生成的控件
- 单击控件以触发事件
- 页面返回,但控件是使用与步骤4的事件源不匹配的不同it生成的
解决方案是删除控制计数变量。