重写 ASP.NET Boundfield 以支持 Dropdownlist 缺少最后一项功能
如果我把它放在 Gridview 中,我设法覆盖 Boundfield 以显示下拉列表。
protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
{
Control child = null;
Control cellControl = null;
if ((((rowState & DataControlRowState.Edit) != DataControlRowState.Normal) && !this.ReadOnly)
|| ((rowState & DataControlRowState.Insert) != DataControlRowState.Normal))
{
// If data cell is in edit mode, create DropDownList editor for this cell
// and set data properties.
DropDownList box = new DropDownList();
box.Items.Add(DefaultValueText);
box.DataSource = this.GetDataSource();
box.DataMember = this.BusinessObjectName;
box.DataTextField = this.DataTextField;
box.DataValueField = this.DataValueField;
box.AppendDataBoundItems = true;
box.ToolTip = this.HeaderText;
cell.Controls.Add(box);
box.DataBind();
// if in edit mode, prepare dropdown for binding
if ((this.DataField.Length != 0) && ((rowState & DataControlRowState.Edit) != DataControlRowState.Normal))
{
cellControl = box;
}
}
else if (this.DataField.Length != 0) // if in read only mode, prepare cell for binding
{
cellControl = cell;
}
if ((cellControl != null) && base.Visible)
{
cellControl.DataBinding += new EventHandler(this.OnDataBindField);
}
}
protected override void OnDataBindField(object sender, EventArgs e)
{
Control control = (Control)sender;
Control namingContainer = control.NamingContainer;
object dataValue = this.GetValue(namingContainer);
bool encode = (this.SupportsHtmlEncode && this.HtmlEncode) && (control is TableCell);
string str = this.FormatDataValue(dataValue, encode);
if (control is TableCell)
{
if (str.Length == 0)
{
str = " ";
}
((TableCell)control).Text = str;
}
else
{
//If data cell is in edit mode, set selected value of DropDownList
if (dataValue != null)
{
DropDownList dropDownList = (DropDownList) control;
ListItem itm = dropDownList.Items.FindByText(dataValue.ToString());
if (itm != null)
{
dropDownList.Text = itm.Value;
}
else
((DropDownList)control).Text = DefaultValueText;
}
}
}
我添加的最后一个功能是在未选择任何内容的情况下显示的默认值/附加项目,例如“请选择”。我可以通过 OnDataBind 事件中的属性 DefaultValueText 进行设置。
现在这是我面临的问题:
在InitializeDataCell中,如果我设置
box.AppendDataBoundItems = true;
并调用
box.DataBind();
下拉列表,则包含所有项目以及附加的默认项目。 它在 OnDataBind 事件中也能很好地工作,如果数据绑定项不包含值,我现在可以在其中选择默认值。
但是当下拉列表显示在网格视图中时,它包含默认值以及来自数据源两次的所有内容,因为我设置了 AppendDataBoundItems = true,这导致下拉列表在添加项目时不会清除其项目 gridview 必须调用 databind 两次,但它只在 OnDataBind 事件方法中注册一次。我只在那里看到一个调用,在那一刻,一切都很好,下拉列表包含默认项目以及数据源中的每个项目之一。
有什么建议可以在哪里或如何处理数据绑定,以便我可以完全控制数据绑定?
I managed to override the Boundfield to display a dropdownlist if I put it in a Gridview.
protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
{
Control child = null;
Control cellControl = null;
if ((((rowState & DataControlRowState.Edit) != DataControlRowState.Normal) && !this.ReadOnly)
|| ((rowState & DataControlRowState.Insert) != DataControlRowState.Normal))
{
// If data cell is in edit mode, create DropDownList editor for this cell
// and set data properties.
DropDownList box = new DropDownList();
box.Items.Add(DefaultValueText);
box.DataSource = this.GetDataSource();
box.DataMember = this.BusinessObjectName;
box.DataTextField = this.DataTextField;
box.DataValueField = this.DataValueField;
box.AppendDataBoundItems = true;
box.ToolTip = this.HeaderText;
cell.Controls.Add(box);
box.DataBind();
// if in edit mode, prepare dropdown for binding
if ((this.DataField.Length != 0) && ((rowState & DataControlRowState.Edit) != DataControlRowState.Normal))
{
cellControl = box;
}
}
else if (this.DataField.Length != 0) // if in read only mode, prepare cell for binding
{
cellControl = cell;
}
if ((cellControl != null) && base.Visible)
{
cellControl.DataBinding += new EventHandler(this.OnDataBindField);
}
}
protected override void OnDataBindField(object sender, EventArgs e)
{
Control control = (Control)sender;
Control namingContainer = control.NamingContainer;
object dataValue = this.GetValue(namingContainer);
bool encode = (this.SupportsHtmlEncode && this.HtmlEncode) && (control is TableCell);
string str = this.FormatDataValue(dataValue, encode);
if (control is TableCell)
{
if (str.Length == 0)
{
str = " ";
}
((TableCell)control).Text = str;
}
else
{
//If data cell is in edit mode, set selected value of DropDownList
if (dataValue != null)
{
DropDownList dropDownList = (DropDownList) control;
ListItem itm = dropDownList.Items.FindByText(dataValue.ToString());
if (itm != null)
{
dropDownList.Text = itm.Value;
}
else
((DropDownList)control).Text = DefaultValueText;
}
}
}
The last feature I added is a default value/ additional item to display if nothing has been selected, like "please select" for example. I can set this through the property DefaultValueText in the OnDataBind event.
Now here's the problem I am facing:
In InitializeDataCell, if I set
box.AppendDataBoundItems = true;
and call
box.DataBind();
The dropdownlist has all the items plus the additional default item.
It also works nicely in the OnDataBind event, where I can now select the default if the databound item does not contain a value.
But when the dropdownlist is displayed in the gridview, it contains the default value plus everything from the datasource TWICE, because I set AppendDataBoundItems = true, which leads the dropdown to NOT clear it's items when items are added
The gridview must be calling databind twice, but it's only registering once in the OnDataBind event method. I only see one call there, and in that moment, everything is fine, the dropdown contains the default item plus one of each item from the datasource.
Any suggestions where or how I can handle the databinding so that I have full control over the databinding?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我设法让它工作
我将用于设置 selectedValue 的所有代码移至 DropDownList 的 DataBound 事件。在这种情况下,数据绑定已经发生,并且值列表可供我设置 selectedValue。我自己不再调用 DataBind,因为无论如何它都会在控件上被调用。我只在开头添加“进行选择”项并将 AppendDataBoundItems 设置为 true。
现在在某些只读状态下可能会出现未处理的情况,因为我不处理任何 Cell.Databinding() 事件。
感兴趣的人可以查看完整的源代码...
它基于 Javad Zarrinabadi 的示例,位于 CodeProjct
用法:
类:
}
I managed to get it working
I moved all the code for setting the selectedValue to the DataBound event of the DropDownList. In this event, the databinding already happened and the list of values is available for me to set the selectedValue. I don't call DataBind myself anymore, since it's being called anyway on the control. I only add the "make a selection" item at the beginning and set AppendDataBoundItems to true.
There might be unhandled situations now in certain read only states, because I don't handle any Cell.Databinding() events.
Complete sourcecode for those who are interested...
It's based on the example from Javad Zarrinabadi at CodeProjct
usage:
Class:
}
好吧,我知道在某些情况下它确实会绑定多次(在更改条件等时),因此您必须再次处理此问题......您可以清除列表并重新绑定吗?
Well, I know in some situations it does bind multiple times (upon changing criteria, etc.) so you are bound to deal with this issue again... can you clear the list and rebind?