我创建了一个自定义DataControlField
,用于DetailsView
显示可编辑的时间表。这些自定义字段中的每一个都有传入的 DataSourceID 字符串,用于填充用户可以选择的值。
如果 DetailsView 处于编辑模式,它将显示 aDropDownList
让用户从来自 a 的项目列表中进行选择SqlDataSource
。在ReadOnly模式下,显示所选值的全名。
我在ReadOnly模式下遇到的问题是,我只有传入的 SqlDataSource 的 ID,当尝试将其转换为实际的 SqlDataSource 对象时,它返回 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 置于编辑模式时,效果很好。失败的地方是 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对象为空。
我的问题是,如何将控件名称的字符串转换为具有 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
}