问题描述
我在GridView中动态添加列时遇到问题。我需要根据DropDownList中的值来更改布局(即包含的列)。当用户更改此列表中的选择时,我需要删除除第一列之外的所有内容,并根据选择动态添加其他列。
我只定义了一列在我的标记 - 列0中,一个模板列,其中我声明一个选择链接和另一个应用程序特定的LinkButton。那个列需要永远在那里。当创建ListBoxSelection时,我删除除第一列之外的所有列,然后重新添加所需的列(在此示例中,我简化了它以始终添加标题列)。以下是代码的一部分:
RemoveVariableColumnsFromGrid();
BoundField b = new BoundField();
b.DataField =标题;
this.gvPrimaryListView.Columns.Add(b);
this.gvPrimaryListView.DataBind();
private void RemoveVariableColumnsFromGrid(){
int ColCount = this.gvPrimaryListView.Columns.Count;
//离开列0 - 我们的选择和查看模板列
while(ColCount> 1){
this.gvPrimaryListView.Columns.RemoveAt(ColCount - 1);
--ColCount;
}
}
此代码第一次运行,我看到静态列和动态添加的标题列。但是,下一次进行选择时,第一列生成为空(其中没有内容)。我看到标题列,我看到左边的第一列 - 但是内部没有任何内容。在调试器中,我可以看到gvPrimaryListView确实还有两列,第一列(索引0)确实是一个模板列。实际上,这个列甚至保留了它在下面的标记中设置为165px的宽度(用于调试目的)。
任何想法?
< asp:GridView ID =gvPrimaryListViewrunat =serverWidth =100%AutoGenerateColumns =false
DataKeyNames =Document_ID EnableViewState =trueDataSourceID =odsPrimaryDataSource
AllowPaging =trueAllowSorting =truePageSize =10OnPageIndexChanging =activeListView_PageIndexChanging
AutoGenerateSelectButton =FalseOnSelectedIndexChanged =activeListView_SelectedIndexChanged
Visible =trueOnRowDataBound =CtlDocList_RowDataBoundFont-Size =8ptFont-Names =Helvetica>
<列>
< asp:TemplateField ShowHeader =false>
< ItemTemplate>
< asp:LinkButton EnableTheming =falseID =CtlSelectDocRowBtnrunat =serverText =Select
CommandName =SelectCssClass =gridbuttonOnClick =RowSelectBtn_Click/> ;
< asp:ImageButton EnableTheming =falseID =DocViewBtnrunat =serverImageUrl =../../ images / ViewDoc3.png
CssClass =gridbuttonCommandName = 选择OnClick =DocViewBtn_Click/>
< / ItemTemplate>
< ItemStyle Width =165px/>
< / asp:TemplateField>
< / Columns>
< EmptyDataTemplate>
< asp:Label ID =Label6runat =serverText =找不到行。 SkinID = LabelHeader >< / ASP:标签>
< / EmptyDataTemplate>
< / asp:GridView>
只需一些其他信息。
它与第一列无关,事实上它与TemplateField无关。如果我在左边放了一个普通的列(在标记中)并将TemplateField列向右移动,则第一列呈现罚款,(现在第二个)TemplateField列消失。
$ b $另一个奇怪的是 - 第一个回发 - 或第二个 - 并不会发生这个问题 - 但是它会从第三个回发开始,然后继续进行后续的回发。我被困了。
我最近征服了gridview中动态列的silmilar问题,也许这将有所帮助。
首先关闭viewstate
第二次在oninit事件中触发的函数中以列编程方式添加列
最后我用以下帮助器类使得复选框在RowDataBound事件启动时实例化。有一些是硬编码的。
这里是所有的代码。有了它:) Warrenty as is,blah blah blah ...
最后,因为我刚刚得到我的脚湿DotNet任何提示将不胜感激[IE不要撕我太多:)]。是的,借用网站上的初始代码,对不起,我不记得我的头顶:(
- 在受保护的覆盖中触发此void OnInit
private void GridViewProject_AddColumns()
{
DataSet dsDataSet = new DataSet();
TemplateField templateField = null;
try
{
StoredProcedure sp = new StoredProcedure(ExpenseReportItemType_GetList,INTRANETWEBDB,Context.User.Identity.Name);
dsDataSet = sp.GetDataSet();
if(sp.RC!= 0&& sp.RC!= 3000)
{
labelMessage.Text = ErrorMessage;
}
int iIndex = 0;
int iCount = dsDataSet.Tables [0] .Rows.Count;
string strCategoryID =;
string strCategoryName =;
iStaticColumnCount = GridViewProject.Columns.Coun t;
//将所有列立即插入到LAST列的左侧
while(iIndex< iCount)
{
strCategoryName = dsDataSet.Tables [0] .Rows [iIndex] [CategoryName]。ToString();
strCategoryID = dsDataSet.Tables [0] .Rows [iIndex] [CategoryID]。ToString();
templateField = new TemplateField();
templateField.HeaderTemplate = new GridViewTemplateExternal(DataControlRowType.Header,strCategoryName,strCategoryID);
templateField.ItemTemplate = new GridViewTemplateExternal(DataControlRowType.DataRow,strCategoryName,strCategoryID);
templateField.FooterTemplate = new GridViewTemplateExternal(DataControlRowType.Footer,strCategoryName,strCategoryID);
//在编辑行
之前,必须将iStaticColumnCount取消插入动态列GridViewProject.Columns.Insert((iIndex +(iStaticColumnCount-1)),templateField);
iIndex ++;
}
iFinalColumnCount = GridViewProject.Columns.Count;
iERPEditColumnIndex =(iFinalColumnCount - 1); // iIndex为零,Count不是
}
catch(异常异常)
{
labelMessage.Text = exception.Message;
}
}
- 助手类
public class GridViewTemplateExternal:System.Web.UI.ITemplate
{
#region Fields
public DataControlRowType DataRowType;
private string strCategoryID;
private string strColumnName;
#endregion
#region构造函数
public GridViewTemplateExternal(DataControlRowType类型,字符串ColumnName,字符串CategoryID)
{
DataRowType = type; // Header,DataRow,
strColumnName = ColumnName; //标题名称
strCategoryID = CategoryID;
}
#endregion
#region方法
public void InstantiateIn(System.Web.UI.Control container)
{
开关( DataRowType)
{
case DataControlRowType.Header:
//构建此列的标题
标签labelHeader = new Label();
labelHeader.Text =< b> + strColumnName +< / b>;
//所有复选框查找到此信息的标题行
labelHeader.Attributes [ERICategoryID] = strCategoryID;
labelHeader.Style [writing-mode] =tb-rl;
labelHeader.Style [filter] =flipv fliph;
container.Controls.Add(labelHeader);
break;
case DataControlRowType.DataRow:
CheckBox checkboxAllowedRow = new CheckBox();
checkboxAllowedRow.Enabled = false;
checkboxAllowedRow.DataBinding + = new EventHandler(this.CheckBox_DataBinding);
container.Controls.Add(checkboxAllowedRow);
break;
case DataControlRowType.Footer:
//没有页脚添加行的数据处理
CheckBox checkboxAllowedFooter = new CheckBox();
container.Controls.Add(checkboxAllowedFooter);
break;
默认值:
break;
}
}
public void CheckBox_DataBinding(Object sender,EventArgs e)
{
CheckBox checkboxAllowed =(CheckBox)sender; //获取引发此事件的控件
GridViewRow row =(GridViewRow)checkboxAllowed.NamingContainer; //获取包含行
string RawValue = DataBinder.Eval(row.DataItem,strColumnName).ToString();
if(RawValue.ToUpper()==TRUE)
{
checkboxAllowed.Checked = true;
}
else
{
checkboxAllowed.Checked = false;
}
}
#endregion
}
I'm having a problem dynamically adding columns to a GridView. I need to change the layout -- i.e. the included columns -- based on the value in a DropDownList. When the user changes the selection in this list, I need to remove all but the first column and dynamically add additional columns based on the selection.
I have only one column defined in my markup -- column 0, a template column, in which I declare a Select link and another application specific LinkButton. That column needs to always be there. When the ListBoxSelection is made, I remove all but the first column and then re-add the desired columns (in this sample, I've simplified it to always add a "Title" column). Here is a portion of the code:
RemoveVariableColumnsFromGrid();
BoundField b = new BoundField();
b.DataField = "Title";
this.gvPrimaryListView.Columns.Add(b);
this.gvPrimaryListView.DataBind();
private void RemoveVariableColumnsFromGrid() {
int ColCount = this.gvPrimaryListView.Columns.Count;
//Leave column 0 -- our select and view template column
while (ColCount > 1) {
this.gvPrimaryListView.Columns.RemoveAt(ColCount - 1);
--ColCount;
}
}
The first time this code runs through, I see both the static column and the dynamically added "Title" column. However, the next time a selection is made, the first column is generated empty (nothing in it). I see the title column, and I see the first column to its left -- but there's nothing generated within it. In the debugger, I can see that gvPrimaryListView does indeed still have two columns and the first one (index 0) is indeed a template column. In fact, the column even retains it's width which is set as 165px in the markup below (for debugging purposes).
Any ideas?
<asp:GridView ID="gvPrimaryListView" runat="server" Width="100%" AutoGenerateColumns="false"
DataKeyNames="Document_ID" EnableViewState="true" DataSourceID="odsPrimaryDataSource"
AllowPaging="true" AllowSorting="true" PageSize="10" OnPageIndexChanging="activeListView_PageIndexChanging"
AutoGenerateSelectButton="False" OnSelectedIndexChanged="activeListView_SelectedIndexChanged"
Visible="true" OnRowDataBound="CtlDocList_RowDataBound" Font-Size="8pt" Font-Names="Helvetica">
<Columns>
<asp:TemplateField ShowHeader="false">
<ItemTemplate>
<asp:LinkButton EnableTheming="false" ID="CtlSelectDocRowBtn" runat="server" Text="Select"
CommandName="Select" CssClass="gridbutton" OnClick="RowSelectBtn_Click" />
<asp:ImageButton EnableTheming="false" ID="DocViewBtn" runat="server" ImageUrl="../../images/ViewDoc3.png"
CssClass="gridbutton" CommandName="Select" OnClick="DocViewBtn_Click" />
</ItemTemplate>
<ItemStyle Width="165px" />
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
<asp:Label ID="Label6" runat="server" Text="No rows found." SkinID="LabelHeader"></asp:Label>
</EmptyDataTemplate>
</asp:GridView>
Just some additional information.
It has nothing to do with the fact that it is the first column but everything to do with the fact that it is a TemplateField. If I put a normal column to the left (in the markup) and shift the TemplateField column to the right, the first column renders fine, and the (now second) TemplateField column disappears.
Another strange thing -- the problem doesn't happen the first postback -- OR THE SECOND -- but it starts on the third postback and then continues for subsequent postbacks. I'm stumped.
I recently conquered silmilar issues with dynamic columns in gridviews, perhaps this will help.
First turn the viewstate off
Second add the columns programatically in a function fired in the oninit event
Lastly I used the following helper class to cause the checkboxes to instantiate when the RowDataBound event kicked off. Yes some of it is hard coded.
Heck here is all the code. Have at it :) Warrenty as is, blah blah blah...
Finally since I am just getting my feet wet DotNet any tips would be appreciated [IE don't rip me too much :) ]. And yes 'borrowed' the initial code from the web somewhere, sorry I cant remember off the top of my head :(
-- Fire this off in protected override void OnInit
private void GridViewProject_AddColumns()
{
DataSet dsDataSet = new DataSet();
TemplateField templateField = null;
try
{
StoredProcedure sp = new StoredProcedure("ExpenseReportItemType_GetList", "INTRANETWEBDB", Context.User.Identity.Name);
dsDataSet = sp.GetDataSet();
if (sp.RC != 0 && sp.RC != 3000)
{
labelMessage.Text = sp.ErrorMessage;
}
int iIndex = 0;
int iCount = dsDataSet.Tables[0].Rows.Count;
string strCategoryID = "";
string strCategoryName = "";
iStaticColumnCount = GridViewProject.Columns.Count;
// Insert all columns immediatly to the left of the LAST column
while (iIndex < iCount)
{
strCategoryName = dsDataSet.Tables[0].Rows[iIndex]["CategoryName"].ToString();
strCategoryID = dsDataSet.Tables[0].Rows[iIndex]["CategoryID"].ToString();
templateField = new TemplateField();
templateField.HeaderTemplate = new GridViewTemplateExternal(DataControlRowType.Header, strCategoryName, strCategoryID);
templateField.ItemTemplate = new GridViewTemplateExternal(DataControlRowType.DataRow, strCategoryName, strCategoryID);
templateField.FooterTemplate = new GridViewTemplateExternal(DataControlRowType.Footer, strCategoryName, strCategoryID);
// Have to decriment iStaticColumnCount to insert dynamic columns BEFORE the edit row
GridViewProject.Columns.Insert((iIndex + (iStaticColumnCount-1)), templateField);
iIndex++;
}
iFinalColumnCount = GridViewProject.Columns.Count;
iERPEditColumnIndex = (iFinalColumnCount - 1); // iIndex is zero based, Count is not
}
catch (Exception exception)
{
labelMessage.Text = exception.Message;
}
}
-- Helper Class
public class GridViewTemplateExternal : System.Web.UI.ITemplate
{
#region Fields
public DataControlRowType DataRowType;
private string strCategoryID;
private string strColumnName;
#endregion
#region Constructor
public GridViewTemplateExternal(DataControlRowType type, string ColumnName, string CategoryID)
{
DataRowType = type; // Header, DataRow,
strColumnName = ColumnName; // Header name
strCategoryID = CategoryID;
}
#endregion
#region Methods
public void InstantiateIn(System.Web.UI.Control container)
{
switch (DataRowType)
{
case DataControlRowType.Header:
// build the header for this column
Label labelHeader = new Label();
labelHeader.Text = "<b>" + strColumnName + "</b>";
// All CheckBoxes "Look Up" to the header row for this information
labelHeader.Attributes["ERICategoryID"] = strCategoryID;
labelHeader.Style["writing-mode"] = "tb-rl";
labelHeader.Style["filter"] = "flipv fliph";
container.Controls.Add(labelHeader);
break;
case DataControlRowType.DataRow:
CheckBox checkboxAllowedRow = new CheckBox();
checkboxAllowedRow.Enabled = false;
checkboxAllowedRow.DataBinding += new EventHandler(this.CheckBox_DataBinding);
container.Controls.Add(checkboxAllowedRow);
break;
case DataControlRowType.Footer:
// No data handling for the footer addition row
CheckBox checkboxAllowedFooter = new CheckBox();
container.Controls.Add(checkboxAllowedFooter);
break;
default:
break;
}
}
public void CheckBox_DataBinding(Object sender, EventArgs e)
{
CheckBox checkboxAllowed = (CheckBox)sender;// get the control that raised this event
GridViewRow row = (GridViewRow)checkboxAllowed.NamingContainer;// get the containing row
string RawValue = DataBinder.Eval(row.DataItem, strColumnName).ToString();
if (RawValue.ToUpper() == "TRUE")
{
checkboxAllowed.Checked = true;
}
else
{
checkboxAllowed.Checked = false;
}
}
#endregion
}
这篇关于向ASP.NET Gridview添加动态列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!