FindControl within DataControlField

本文关键字:DataControlField within FindControl | 更新日期: 2024-10-18 19:59:17

我创建了一个自定义DataControlField,用于DetailsView以显示可编辑的时间表。每个自定义字段都传递了DataSourceID字符串,用于填充用户可以选择的值。

如果DetailsView处于编辑模式,它将显示一个DropDownList,让用户从来自SqlDataSource的项目列表中进行选择。在ReadOnly模式中,显示所选值的全名。

我在ReadOnly模式中遇到的问题是,我所拥有的只是传入的SqlDataSource的ID,当试图将其转换为实际的SqlDataSources对象时,它会返回null。

我已经把整个对象放在底部,以防将来对任何人有用,并尝试这样做。

代码前端看起来像这个

<asp:DetailsView ID="dvPayPeroid1" runat="server"
    AutoGenerateRows="False"
    CssClass="DetailsView"
    DataSourceID="sqlMyScheduleData"
    DefaultMode="ReadOnly"
    GridLines="None">
    <FieldHeaderStyle CssClass="DetailsViewHeader" />
    <Fields>
        <asp:BoundField DataField="FirstDayOfWeek" HeaderText="Week Starting" HtmlEncode="false" DataFormatString="{0:MM/dd/yyyy}" ReadOnly="true" />
        <my:ScheduleField DataField="1" HeaderText="Sunday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="2" HeaderText="Monday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="3" HeaderText="Tuesday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="4" HeaderText="Wednesday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="5" HeaderText="Thursday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="6" HeaderText="Friday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="7" HeaderText="Saturday" DataSourceID="sqlReasonCodes" />
        <asp:BoundField DataField="FirstDayOfSecondWeek" HeaderText="Week Starting" HtmlEncode="false" DataFormatString="{0:MM/dd/yyyy}" ReadOnly="true" />
        <my:ScheduleField DataField="8" HeaderText="Sunday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="9" HeaderText="Monday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="10" HeaderText="Tuesday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="11" HeaderText="Wednesday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="12" HeaderText="Thursday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="13" HeaderText="Friday" DataSourceID="sqlReasonCodes" />
        <my:ScheduleField DataField="14" HeaderText="Saturday" DataSourceID="sqlReasonCodes" />
    </Fields>
</asp:DetailsView>
<asp:SqlDataSource ID="sqlReasonCodes" runat="server" 
    CacheDuration="500"
    ConnectionString="<%$ ConnectionStrings:MyConnectionString %>"
    EnableCaching="true"
    SelectCommand="ReasonSelectActive" SelectCommandType="StoredProcedure">
</asp:SqlDataSource>

当我将DetailsView设置为编辑模式时,效果非常好。如果is失败,则处于ReadOnly模式,该模式在DataField属性中传递,其值为"P"表示"PTO","W"表示"Working","R"表示"Requested Day Off"等。

我的问题是将DataField转换为相应的长名称。目前,我正在使用这段代码来获取SqlDataSource。

Page page = (Page)HttpContext.Current.Handler;
SqlDataSource sds = (SqlDataSource)page.FindControl(this.DataSourceID);
DataView dv = (DataView)sds.Select(DataSourceSelectArguments.Empty);

此处sds对象为空。

我的问题是,如何将Control名称的字符串转换为具有DataControlField的对象?

下面的代码供参考,如果有人对代码有改进建议,一定要告诉我。

public class ScheduleField : DataControlField
{
    #region Properties
    public string CssClass
    {
        get
        {
            object value = ViewState["CssClass"];
            if (value != null)
                return value.ToString();
            return "MetricStatus";
        }
        set
        {
            ViewState["CssClass"] = value;
            OnFieldChanged();
        }
    }
    public string DataSourceID
    {
        get
        {
            object value = ViewState["DataSourceID"];
            if (value != null)
                return Convert.ToString(value);
            return "";
        }
        set
        {
            ViewState["DataSourceID"] = value;
            OnFieldChanged();
        }
    }
    public string DataField
    {
        get
        {
            object value = ViewState["DataField"];
            if (value != null)
                return Convert.ToString(value);
            return "";
        }
        set
        {
            ViewState["DataField"] = value;
            OnFieldChanged();
        }
    }
    #endregion
    #region Constructors
    public ScheduleField()
    {
    }
    #endregion
    #region Abstract / Override Implementations
    protected override DataControlField CreateField()
    {
        return new BoundField();
    }
    public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
    {
        base.InitializeCell(cell, cellType, rowState, rowIndex);
        // add controls to the cell here.
        if (cellType == DataControlCellType.DataCell)
        {
            if ((rowState & DataControlRowState.Edit) > 0)
                cell.DataBinding += new EventHandler(cell_DataBinding_Edit);
            else if (rowState == DataControlRowState.Normal || rowState == DataControlRowState.Alternate)
                cell.DataBinding += new EventHandler(cell_DataBinding_Normal);
            else
                throw new Exception("Unhandled rowState: " + rowState.ToString());
        }
    }
    #endregion
    #region Events
    private void cell_DataBinding_Edit(object sender, EventArgs e)
    {
        DataControlFieldCell cell = (DataControlFieldCell)sender;
        object dataItem = DataBinder.GetDataItem(cell.NamingContainer);
        string sDataField = DataBinder.GetPropertyValue(dataItem, DataField).ToString();
        DropDownList ddlReason = new DropDownList();
        ddlReason.Items.Add(new ListItem("<none>", ""));
        ddlReason.AppendDataBoundItems = true;
        ddlReason.DataSourceID = this.DataSourceID;
        ddlReason.DataTextField = "Name";
        ddlReason.DataValueField = "Short";
        ddlReason.SelectedValue = sDataField;
        cell.Controls.Add(ddlReason);
    }
    private void cell_DataBinding_Normal(object sender, EventArgs e)
    {
        DataControlFieldCell cell = (DataControlFieldCell)sender;
        object dataItem = DataBinder.GetDataItem(cell.NamingContainer);
        string sDataField = DataBinder.GetPropertyValue(dataItem, DataField).ToString();
        Page page = (Page)HttpContext.Current.Handler;
        SqlDataSource sds = (SqlDataSource)page.FindControl(this.DataSourceID);
        DataView dv = (DataView)sds.Select(DataSourceSelectArguments.Empty);
        DataTable dt = dv.ToTable();
        foreach (DataRow dr in dt.Rows)
        {
            if (dr["Short"].ToString() == sDataField)
                sDataField = dr["Name"].ToString();
        }
        Label lblReason = new Label();
        lblReason.Text = sDataField;
        cell.Controls.Add(lblReason);
    }
    #endregion
    #region Methods
    // no methods
    #endregion
}

FindControl within DataControlField

代替.parent.parent。。。用途:

ContentPlaceHolder cph = (ContentPlaceHolder)this.Page.Master.FindControl("ContentPlaceHolderID");

好吧,这看起来像是一个完整的破解,但以下是我如何引用SqlDataSource的。

ContentPlaceHolder cph = (ContentPlaceHolder)cell.Parent.Parent.Parent.Parent;
SqlDataSource sds = (SqlDataSource)cph.FindControl("sqlReasonCodes");
DataView dv = (DataView)sds.Select(DataSourceSelectArguments.Empty);

由于我使用的是MasterPage,所以在其他区域中,普通的Page对象似乎并不存在。

我愿意接受比.Parent.Parent.Parent.Parent更好的想法。

相关文章:
  • 没有找到相关文章