我已经尝试了几个小时,但无法弄清楚为什么我不能成功使用带有ITemplate派生类和SqlDataSource动态创建的字段的DetailsView插入记录。
以下是用于创建模板的代码:
public class DetailsViewTemplate : ITemplate
{
private DataControlRowType templateType;
private string columnNameFriendly;
private string columnNameData;
private Control control;
private DetailsViewMode viewMode;
public DetailsViewTemplate(DataControlRowType type, DetailsViewMode mode, string colNameFr, string colNameDt, Control con)
{
templateType = type;
columnNameFriendly = colNameFr;
columnNameData = colNameDt;
control = con;
viewMode = mode;
}
public void InstantiateIn(System.Web.UI.Control container)
{
switch (templateType)
{
case DataControlRowType.Header:
{
Literal lc = new Literal();
lc.Text = columnNameFriendly;
container.Controls.Add(lc);
break;
}
case DataControlRowType.DataRow:
{
Control field = control;
if (field.GetType() == typeof(Label))
{
Label lbl = (Label)control; // new Label();
if (viewMode != DetailsViewMode.Insert)
lbl.DataBinding += new EventHandler(this.lbl_DataBind);
container.Controls.Add(control);
}
else if (field.GetType() == typeof(TextBox))
{
TextBox txt = (TextBox)control; // new TextBox();
if (viewMode != DetailsViewMode.Insert)
txt.DataBinding += new EventHandler(this.txt_DataBind);
container.Controls.Add(control);
}
else if (field.GetType() == typeof(DropDownList))
{
DropDownList ddl = (DropDownList)field;
if (viewMode != DetailsViewMode.Insert)
ddl.DataBinding += new EventHandler(this.ddl_DataBind);
container.Controls.Add(control);
}
else if (field.GetType() == typeof(CheckBox))
{
CheckBox cbx = (CheckBox)control; // new CheckBox();
if (viewMode != DetailsViewMode.Insert)
cbx.DataBinding += new EventHandler(this.cbx_DataBind);
container.Controls.Add(control);
}
break;
}
}
}
private void txt_DataBind(Object sender, EventArgs e)
{
TextBox txt = (TextBox)sender;
DetailsView container = (DetailsView)txt.NamingContainer;
if (((DataRowView)container.DataItem) != null)
txt.Text = DataBinder.Eval(((DataRowView)container.DataItem), columnNameData).ToString();
//txt.Font.Size = 7;
txt.Font.Name = "Arial";
}
private void lbl_DataBind(Object sender, EventArgs e)
{
Label lbl = (Label)sender;
DetailsView container= (DetailsView)lbl.NamingContainer;
if (((DataRowView)container.DataItem) != null)
lbl.Text = DataBinder.Eval(((DataRowView)container.DataItem), columnNameData).ToString();
//lbl.Font.Size = 7;
lbl.Font.Name = "Arial";
}
private void ddl_DataBind(Object sender, EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
DetailsView container = (DetailsView)ddl.NamingContainer;
if (((DataRowView)container.DataItem) != null)
ddl.SelectedValue = DataBinder.Eval(((DataRowView)container.DataItem), columnNameData).ToString();
//ddl.Font.Size = 7;
ddl.Font.Name = "Arial";
}
private void cbx_DataBind(Object sender, EventArgs e)
{
CheckBox cbx = (CheckBox)sender;
DetailsView container = (DetailsView)cbx.NamingContainer;
if (((DataRowView)container.DataItem) != null)
cbx.Checked = (bool)DataBinder.Eval(((DataRowView)container.DataItem), columnNameData);
}
}`
以下是将模板字段添加到DetailsView
的代码 TextBox tb = new TextBox();
TemplateField tf = new TemplateField();
tf.HeaderTemplate = new DetailsViewTemplate(DataControlRowType.Header, DetailsViewDynAttachment.DefaultMode, fieldName, fieldName, new Label());
tf.InsertItemTemplate = new DetailsViewTemplate(DataControlRowType.DataRow, DetailsViewDynAttachment.DefaultMode, fieldName, fieldName, tb);
DetailsViewDynAttachment.Fields.Add(TF);
DetailsView模式设置为Insert,InserCommand和oparameters列表被定义但是无论我使用内置的Insert命令或在数据源上调用insert我尝试的所有动态添加的控件似乎都有在回发之后消失了所有的价值观......
请注意,相同的代码在ReadOnly模式下工作(使用SelectCommand设置...) 但无法理解为什么字段似乎不会在插入模式下持久存在。
我搜索了几个小时并尝试了我所做的一切,但找不到解决方案...... 任何帮助将不胜感激。
P.S。
这里的主要问题是动态添加的模板字段在回发后不会持久化。 DetailsView字段和行是1(命令字段),所有其他动态字段都是“丢失”(未保留)。 此外,尽管引发了ItemInserting,但它的(DetailsViewInsertEventArgs)e.Values计数为0.值没有持久...(?)
为什么?
答案 0 :(得分:1)
我找到了解决方案!所以我想发布它,以防它可以帮助任何想做类似事情的人。
我的原型中存在一些问题:
1-必须使用IBindableTemplate来实现双向绑定。这个类添加到用于实现读取绑定的InstantiateIn函数中,一个名为ExtractValues的函数,您必须覆盖该函数以反向实现绑定(插入时)。
此函数用于从动态创建的控件中提取值,并将它们作为OrderedDictionary实例返回。
2-这是一个棘手的部分:必须在Page_Init事件中创建动态模板字段。否则该字段将不会保留。我不会冒风险解释为什么虽然我认为我理解......任何人? ; - )
这里是DetailsViewTemplate的更新版本:IBindableTemplate类:
public class DetailsViewTemplate : IBindableTemplate
{
private DataControlRowType templateType;
private string columnNameFriendly;
private string columnNameData;
private Control control;
private DetailsViewMode viewMode;
//+=========================================================================+
public DetailsViewTemplate(DataControlRowType type, DetailsViewMode mode, string colNameFr, string colNameDt, Control con)
{
templateType = type;
columnNameFriendly = colNameFr;
columnNameData = colNameDt;
control = con;
viewMode = mode;
}
//+=========================================================================+
void ITemplate.InstantiateIn(System.Web.UI.Control container)
{
switch (templateType)
{
case DataControlRowType.Header:
{
Literal lc = new Literal();
lc.Text = columnNameFriendly;
container.Controls.Add(lc);
break;
}
case DataControlRowType.DataRow:
{
if (control.GetType() == typeof(Label))
{
Label lbl = (Label)control; // new Label();
if (viewMode != DetailsViewMode.Insert)
lbl.DataBinding += new EventHandler(this.lbl_DataBind);
container.Controls.Add(control);
}
else if (control.GetType() == typeof(TextBox))
{
TextBox txt = (TextBox)control; // new TextBox();
if (viewMode != DetailsViewMode.Insert)
txt.DataBinding += new EventHandler(this.txt_DataBind);
container.Controls.Add(control);
}
else if (control.GetType() == typeof(DropDownList))
{
DropDownList ddl = (DropDownList)control;
if (viewMode != DetailsViewMode.Insert)
ddl.DataBinding += new EventHandler(this.ddl_DataBind);
container.Controls.Add(control);
}
else if (control.GetType() == typeof(CheckBox))
{
CheckBox cbx = (CheckBox)control; // new CheckBox();
if (viewMode != DetailsViewMode.Insert)
cbx.DataBinding += new EventHandler(this.cbx_DataBind);
container.Controls.Add(control);
}
break;
}
}
}
//+=========================================================================+
private void txt_DataBind(Object sender, EventArgs e)
{
TextBox txt = (TextBox)sender;
DetailsView container = (DetailsView)txt.NamingContainer;
if (((DataRowView)container.DataItem) != null)
txt.Text = DataBinder.Eval(((DataRowView)container.DataItem), columnNameData).ToString();
//txt.Font.Size = 7;
txt.Font.Name = "Arial";
}
//+=========================================================================+
private void lbl_DataBind(Object sender, EventArgs e)
{
Label lbl = (Label)sender;
DetailsView container = (DetailsView)lbl.NamingContainer;
if (((DataRowView)container.DataItem) != null)
lbl.Text = DataBinder.Eval(((DataRowView)container.DataItem), columnNameData).ToString();
//lbl.Font.Size = 7;
lbl.Font.Name = "Arial";
}
//+=========================================================================+
private void ddl_DataBind(Object sender, EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
DetailsView container = (DetailsView)ddl.NamingContainer;
if (((DataRowView)container.DataItem) != null)
ddl.SelectedValue = DataBinder.Eval(((DataRowView)container.DataItem), columnNameData).ToString();
//ddl.Font.Size = 7;
ddl.Font.Name = "Arial";
}
//+=========================================================================+
private void cbx_DataBind(Object sender, EventArgs e)
{
CheckBox cbx = (CheckBox)sender;
DetailsView container = (DetailsView)cbx.NamingContainer;
if (((DataRowView)container.DataItem) != null)
cbx.Checked = (bool)DataBinder.Eval(((DataRowView)container.DataItem), columnNameData);
}
//+=========================================================================+
IOrderedDictionary IBindableTemplate.ExtractValues(Control container)
{
OrderedDictionary dict = new OrderedDictionary();
if (control.GetType() == typeof(Label))
{
Label lb = (Label)FindControlRecursive(container, columnNameData);
if (lb != null)
dict[columnNameData] = lb.Text;
}
else if (control.GetType() == typeof(TextBox))
{
TextBox tb = (TextBox)FindControlRecursive(container, columnNameData);
if (tb != null)
dict[columnNameData] = tb.Text;
}
else if (control.GetType() == typeof(CheckBox))
{
CheckBox cb = (CheckBox)FindControlRecursive(container, columnNameData);
if (cb != null)
dict[columnNameData] = cb.Checked;
}
else if (control.GetType() == typeof(DropDownList))
{
DropDownList ddl = (DropDownList)FindControlRecursive(container, columnNameData);
if (ddl != null)
dict[columnNameData] = ddl.SelectedValue;
}
return dict;
}
//+=========================================================================+
private Control FindControlRecursive(Control ctlRoot, string sControlId)
{
// if this control is the one we are looking for, break from the recursion
// and return the control.
if (ctlRoot.ID == sControlId)
{
return ctlRoot;
}
// loop the child controls of this parent control and call recursively.
foreach (Control ctl in ctlRoot.Controls)
{
Control ctlFound = FindControlRecursive(ctl, sControlId);
// if we found the control, return it.
if (ctlFound != null)
{
return ctlFound;
}
}
// we never found the control so just return null.
return null;
}
//+=========================================================================+
}
那么,这有什么用呢? 使用此机制,您可以为任何可以获取SqlConnection的表记录创建DetailsView。并且有一些GetSchema魔法。您可以编写代码来编辑在设计时未知的任何表记录。
这是我的追求的目标' ; - )
希望它可能对某些人有用...... 新年快乐 ! (12月31日下午5:14)