自定义边界字段没有';t在添加了LiteralControl的PostBacks之间保留数据

本文关键字:LiteralControl 添加 PostBacks 数据 保留 之间 字段 边界 自定义 | 更新日期: 2023-09-27 18:21:50

我已经创建了一个自定义BoundField,用于在编辑插入模式下使用DetailsView,以利用Twitter引导。

该控件运行良好,除了在InitializeDataCell(…)期间添加额外的LiteralControl s以用一些HTML包围TextBox时。与此相关的代码接近末尾。

下面生成的HTML似乎与TemplateField生成的HTML相同。但是,当我启动Update时,每当它添加此处所示的额外div/spanTextBox中的值在PostBack上为空。

<div class="input-prepend">
    <span class="add-on">$</span>
    <input name="ctl00$ctl00$MainContent$MainContent$pi$dvPackage$tbPrice" type="text" value="0" size="5" id="MainContent_MainContent_pi_dvPackage_tbPrice" title="Price">
</div>

以下是我在前端ASP.NET代码中所做的操作以及生成的HTML的一些示例。

不起作用-自定义字段通过Update命令提交后,文本框内的值将取消设置,仅当我添加输入附加附加

DetailsView内的字段

<my:ValidationField DataField="Price" HeaderText="Price" TextPrepend="$" />

HTML生成

<td>
    <div class="input-prepend">
        <span class="add-on">$</span>
        <input name="ctl00$ctl00$MainContent$MainContent$pi$dvPackage$tbPrice" type="text" value="0" size="5" id="MainContent_MainContent_pi_dvPackage_tbPrice" title="Price">
    </div>
</td>

正常工作-TemplateField工作良好

DetailsView内的字段

<asp:TemplateField>
    <EditItemTemplate>
        <div class="input-prepend">
            <span class="add-on">$</span>
            <asp:TextBox ID="tbCost" runat="server" Text='<%# Bind("Cost") %>'></asp:TextBox>
        </div>
    </EditItemTemplate>
</asp:TemplateField>

HTML生成-与上面的内容相同

<td>
    <div class="input-prepend">
        <span class="add-on">$</span>
        <input name="ctl00$ctl00$MainContent$MainContent$pi$dvPackage$tbPrice" type="text" value="0" size="5" id="MainContent_MainContent_pi_dvPackage_tbPrice" title="Price">
    </div>
</td>

是否有效-使用自定义字段生成HTML当我没有添加TextPrepend字段时,文本框内的值通过Update命令正确提交。

DetailsView内的字段

<my:ValidationField DataField="Price" HeaderText="Price" />

在没有额外span/div的情况下生成的HTML

<td>
    <input name="ctl00$ctl00$MainContent$MainContent$pi$dvPackage$tbPrice" type="text" value="0" size="5" id="MainContent_MainContent_pi_dvPackage_tbPrice" title="Price">
</td>

InitializeDataCell与此代码创建相关的部分

我认为这是由于InitializeDataCell(…)实现的问题。

protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
{
    base.InitializeDataCell(cell, rowState);
    // Find the text box to validate
    TextBox text = FindTextBox(cell);
    if (text != null)
    {
        text.ID = "tb" + DataField;
        text.MaxLength = MaxLength;
        text.TextMode = TextMode;
        text.Text = DataField;
        string cellCss = string.Empty;
        bool prepend = !string.IsNullOrEmpty(this.TextPrepend);
        bool append = !string.IsNullOrEmpty(this.TextAppend);
        bool addon = prepend || append;
        if (prepend == true)
            cellCss = this.ConcatenateCss(cellCss, "input-prepend");
        if (append == true)
            cellCss = this.ConcatenateCss(cellCss, "input-append");
        if (addon == true)
        {
            int textIndex = cell.Controls.IndexOf(text);
            Literal container = new Literal();
            container.Text = "<div class='"" + cellCss + "'">";
            cell.Controls.AddAt(textIndex, container);
        }
        if (prepend == true)
        {
            int textIndex = cell.Controls.IndexOf(text);
            Literal units = new Literal();
            units.Text = "<span class='"add-on'">" + this.Prepend() + "</span>";
            cell.Controls.AddAt(textIndex, units);
        }
        if (append == true)
        {
            Literal units = new Literal();
            units.Text = "<span class='"add-on'">" + this.Append() + "</span>";
            cell.Controls.Add(units);
        }
        if (addon == true)
        {
            Literal container = new Literal();
            container.Text = "</div>";
            cell.Controls.Add(container);
        }
    }
}

整个代码以防对任何试图使用Twitter Bootstrap的人有用,或者我的代码在其他地方出错。

public class ValidationField : BoundField
{
    #region Properties
    public virtual string EditTextCssClass
    {
        get
        {
            return (string)(ViewState["EditTextCssClass"] ?? string.Empty);
        }
        set
        {
            ViewState["EditTextCssClass"] = value;
            OnFieldChanged();
        }
    }
    public virtual ValidatorDisplay ErrorDisplay
    {
        get
        {
            return (ValidatorDisplay)(ViewState["ErrorDisplay"] ?? ValidatorDisplay.Dynamic);
        }
        set
        {
            ViewState["ErrorDisplay"] = value;
            OnFieldChanged();
        }
    }
    public virtual string ErrorMessage
    {
        get
        {
            return (string)(ViewState["ErrorMessage"] ?? "Invalid value entered");
        }
        set
        {
            ViewState["ErrorMessage"] = value;
            OnFieldChanged();
        }
    }
    public virtual string HelpText
    {
        get
        {
            return (string)(ViewState["HelpText"] ?? string.Empty);
        }
        set
        {
            ViewState["HelpText"] = value;
            OnFieldChanged();
        }
    }
    public virtual TwitterBootstrap.WebControls.TextBox.HelpTextDisplayMode HelpDisplay
    {
        get
        {
            return (TwitterBootstrap.WebControls.TextBox.HelpTextDisplayMode)(ViewState["HelpDisplay"] ?? TwitterBootstrap.WebControls.TextBox.HelpTextDisplayMode.Block);
        }
        set
        {
            ViewState["HelpDisplay"] = value;
            OnFieldChanged();
        }
    }
    public virtual int MaxLength
    {
        get
        {
            return (int)(ViewState["MaxLength"] ?? 0);
        }
        set
        {
            ViewState["MaxLength"] = value;
            OnFieldChanged();
        }
    }
    public virtual string PlaceHolder
    {
        get
        {
            return (string)(ViewState["PlaceHolder"] ?? string.Empty);
        }
        set
        {
            ViewState["PlaceHolder"] = value;
            OnFieldChanged();
        }
    }
    public virtual bool Required
    {
        get
        {
            return (bool)(ViewState["Required"] ?? false);
        }
        set
        {
            ViewState["Required"] = value;
            OnFieldChanged();
        }
    }
    public virtual TextBoxMode TextMode
    {
        get
        {
            return (TextBoxMode)(ViewState["TextMode"] ?? TextBoxMode.SingleLine);
        }
        set
        {
            ViewState["TextMode"] = value;
            OnFieldChanged();
        }
    }
    public virtual string ValidationExpression
    {
        get
        {
            return (string)(ViewState["ValidationExpression"] ?? string.Empty);
        }
        set
        {
            ViewState["ValidationExpression"] = value;
            OnFieldChanged();
        }
    }
    public virtual string ValidationGroup
    {
        get
        {
            return (string)(ViewState["ValidationGroup"] ?? string.Empty);
        }
        set
        {
            ViewState["ValidationGroup"] = value;
            OnFieldChanged();
        }
    }
    public virtual string TextAppend
    {
        get
        {
            object value = ViewState["TextAppend"];
            if (value != null)
                return value.ToString();
            return string.Empty;
        }
        set
        {
            ViewState["TextAppend"] = value;
            OnFieldChanged();
        }
    }
    public virtual string TextPrepend
    {
        get
        {
            object value = ViewState["TextPrepend"];
            if (value != null)
                return value.ToString();
            return string.Empty;
        }
        set
        {
            ViewState["TextPrepend"] = value;
            OnFieldChanged();
        }
    }
    #endregion
    public ValidationField()
    {
    }
    protected override DataControlField CreateField()
    {
        return new ValidationField();
    }
    protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
    {
        base.InitializeDataCell(cell, rowState);
        // Find the text box to validate
        TextBox text = FindTextBox(cell);
        if (text != null)
        {
            text.ID = "tb" + DataField;
            text.MaxLength = MaxLength;
            text.TextMode = TextMode;
            text.CssClass = EditTextCssClass;
            text.Text = DataField;
            if (PlaceHolder != string.Empty)
                text.Attributes.Add("placeholder", PlaceHolder);
            string cellCss = string.Empty;
            bool prepend = !string.IsNullOrEmpty(this.TextPrepend);
            bool append = !string.IsNullOrEmpty(this.TextAppend);
            bool addon = prepend || append;
            if (prepend == true)
                cellCss = this.ConcatenateCss(cellCss, "input-prepend");
            if (append == true)
                cellCss = this.ConcatenateCss(cellCss, "input-append");
            if (addon == true)
            {
                int textIndex = cell.Controls.IndexOf(text);
                Literal container = new Literal();
                container.Text = "<div class='"" + cellCss + "'">";
                cell.Controls.AddAt(textIndex, container);
            }
            if (prepend == true)
            {
                int textIndex = cell.Controls.IndexOf(text);
                Literal units = new Literal();
                units.Text = "<span class='"add-on'">" + this.Prepend() + "</span>";
                cell.Controls.AddAt(textIndex, units);
            }
            if (append == true)
            {
                Literal units = new Literal();
                units.Text = "<span class='"add-on'">" + this.Append() + "</span>";
                cell.Controls.Add(units);
            }
            if (addon == true)
            {
                Literal container = new Literal();
                container.Text = "</div>";
                cell.Controls.Add(container);
            }
            if (Required == true)
            {
                Literal required = new Literal();
                required.Text = "<span class='"required'">*</span>";
                cell.Controls.Add(required);
            }
            if (HelpText != string.Empty)
            {
                Label lblHelpText = new Label();
                if (HelpDisplay == TwitterBootstrap.WebControls.TextBox.HelpTextDisplayMode.Block)
                    lblHelpText.CssClass = "help-block";
                else
                    lblHelpText.CssClass = "help-inline";
                lblHelpText.Text = HelpText;
                cell.Controls.Add(lblHelpText);
            }
            if (Required == true)
            {
                // Add a RequiredFieldValidator
                RequiredFieldValidator required = new RequiredFieldValidator();
                required.ErrorMessage = ErrorMessage;
                required.Display = ErrorDisplay;
                required.ControlToValidate = text.ID;
                required.Text = "";
                if (ValidationGroup != string.Empty)
                    required.ValidationGroup = ValidationGroup;
                cell.Controls.Add(required);
            }
            if (ValidationExpression != string.Empty)
            {
                // Add a RequiredFieldValidator
                RegularExpressionValidator regex = new RegularExpressionValidator();
                regex.ErrorMessage = ErrorMessage;
                regex.Display = ErrorDisplay;
                regex.ControlToValidate = text.ID;
                regex.ValidationExpression = ValidationExpression;
                if (ValidationGroup != string.Empty)
                    regex.ValidationGroup = ValidationGroup;
                cell.Controls.Add(regex);
            }
        }
    }
    #region Methods
    private string ConcatenateCss(params string[] classes)
    {
        string result = string.Empty;
        foreach (string s in classes)
            result += s + " ";
        return result.TrimEnd().TrimStart();
    }
    private static TextBox FindTextBox(Control parent)
    {
        TextBox result = null;
        foreach (Control control in parent.Controls)
        {
            if (control is TextBox)
            {
                result = control as TextBox;
                break;
            }
        }
        return result;
    }
    protected virtual string Prepend()
    {
        return this.TextPrepend;
    }
    protected virtual string Append()
    {
        return this.TextAppend;
    }
    #endregion
}

自定义边界字段没有';t在添加了LiteralControl的PostBacks之间保留数据

我设法弄清楚了发生这种情况的原因。由于字段中的Control集合已更改,因此还必须重写_ExtractValuesFromCell(…)to get the TextBox`值。

我使用了一个稍微修改过的ASP.NET实现,Boundfield覆盖以支持Dropdownlist。它缺少最后一个功能,并且没有针对我的用例进行优化。然而,它现在运行良好。

public override void ExtractValuesFromCell(System.Collections.Specialized.IOrderedDictionary dictionary, DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly)
{
    Control control = null;
    string dataField = DataField;
    object text = null;
    string nullDisplayText = NullDisplayText;
    if (((rowState & DataControlRowState.Insert) == DataControlRowState.Normal) || InsertVisible)
    {
        if (cell.Controls.Count > 0)
        {
            foreach (Control c in cell.Controls)
            {
                control = cell.Controls[0];
                if (c is TextBox)
                {
                    text = ((TextBox)c).Text;
                } 
            }
        }
        else if (includeReadOnly)
        {
            string s = cell.Text;
            if (s == "&nbsp;")
            {
                text = string.Empty;
            }
            else if (SupportsHtmlEncode && HtmlEncode)
            {
                text = HttpUtility.HtmlDecode(s);
            }
            else
            {
                text = s;
            }
        }
        if (text != null)
        {
            if (((text is string) && (((string)text).Length == 0)) && ConvertEmptyStringToNull)
            {
                text = null;
            }
            if (((text is string) && (((string)text) == nullDisplayText)) && (nullDisplayText.Length > 0))
            {
                text = null;
            }
            if (dictionary.Contains(dataField))
            {
                dictionary[dataField] = text;
            }
            else
            {
                dictionary.Add(dataField, text);
            }
        }
    }
}