I have created a custom DataControlField which is used in a DetailsView to display an editable schedule. Each of these custom fields has the DataSourceID string passed in which is used to populate the values a user may choose.
If the DetailsView is in Edit mode, it will display a DropDownList to let the user select from a list of items that come from a SqlDataSource. In ReadOnly mode, it is to display the full name of the value selected.
The trouble I have in the ReadOnly mode is that all I have is the ID of the SqlDataSource passed in and when trying to convert it to an actual SqlDataSource object, it returns null.
I’ve put the full object at the bottom in case it’s of use to anyone in the future, trying to do this as well.
The code front looks something like this
<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>
When I place the DetailsView in to Edit mode, it works great. Where is fails is in ReadOnly mode which is passed in the DataField property with values such as “P” for “PTO,” “W” for “Working,” “R” for “Requested Day Off,” etc.
My trouble is converting the DataField to its corresponding long name. Currently I’m using this bit of code to grab the SqlDataSource.
Page page = (Page)HttpContext.Current.Handler;
SqlDataSource sds = (SqlDataSource)page.FindControl(this.DataSourceID);
DataView dv = (DataView)sds.Select(DataSourceSelectArguments.Empty);
Here the sds object is null.
My question is, how do I convert the string of a Control name to an object with a DataControlField?
Code is below for reference and if anyone has a suggestion for improvement to the code by the way, do tell.
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
}
Instead of
.parent.parent… use: