【问题标题】:Inserting a new record with DetailsView created dynamically with ITemplate使用 ITemplate 动态创建 DetailsView 插入新记录
【发布时间】:2014-12-29 23:01:50
【问题描述】:

我已经尝试了几个小时,但无法弄清楚为什么我无法成功地使用 DetailsView 插入记录,其中字段使用 ITemplate 派生类和 SqlDataSource 动态创建。

这是用于创建模板的代码:

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 和 opparameters 列表已定义但无论我尝试什么,只要我使用内置的 Insert 命令或在数据源上调用 insert,我所有动态添加的控件似乎都有回发后消失了,所有的价值都丢失了……

请注意,相同的代码在 ReadOnly 模式下工作(使用 SelectCommand 集...) 但无法弄清楚为什么这些字段似乎没有在插入模式下持久化。

我搜索了几个小时并尝试了所有我想要的方法,但找不到解决方案... 任何帮助将不胜感激。

附言

这里的主要问题是动态添加的模板字段在回发后不会持续存在。 DetailsView Fields and Rows 为 1(命令字段),所有其他动态字段都“丢失”(未保留)。 此外,虽然 ItemInserting 被提出,但它的 (DetailsViewInsertEventArgs) e.Values 计数为 0。值未持久化...(?)

为什么?

【问题讨论】:

    标签: asp.net


    【解决方案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)

    【讨论】:

    • 我对动态编辑模板有问题,但使用 FormView。我无法从 FormViewUpdateEventArgs e protected void FormView1_ItemUpdating(object sender, FormViewUpdateEventArgs e) { EditFormView.UpdateCommand = "UPDATE " + UniqueTable + " SET bla_Opis='" + e.NewValues["bla_Opis"] + " ' WHERE " + PrimaryKey + "=" + ident; EditFormView.Update(); //EditFormView.DataBind();我认为问题在于我用旧值覆盖了 page_init 上的新值。你能发布你的页面初始化方法吗?
    猜你喜欢
    • 1970-01-01
    • 2022-01-12
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多