Introduction
Many ASP.NET applications utilize the DataGrid
control. This control provides the ability to dynamically hide or show a DataGridColumn
by using the index of the column contained in the DataGridColumnsCollection
. For example, if you want to hide the first column in a grid, you can do so by DataGrid.Columns[0].Visible = false;
. A problem I ran into using the column index was when the columns had to be reordered. This can be a nightmare, especially if you have a lot of columns in your grid. Imagine a grid with 20+ columns and you need to move the 11th one to the 5th position and the 20th column to the 2nd position and so on. Every time you do this, you need to modify the column index reference in your code.
I thought to myself, "there has to be a way to retrieve a column by its name". Well, there is no DataGrid.Columns["Name"]
attribute available but, there is Column.HeaderText
. Even if you decide not to display the Header, the HeaderText
value is still available if you set it. To access the HeaderText
in your code-behind, simply loop through the DataGrid
columns and check the HeaderText
.
The Code
Below is an example of the method that dynamically hides and displays the columns. In my example solution, I call the HideShowColumns
after I bind the DataTable
to the grid.
private void HideShowColumns(DataGrid dg)
{
if(dg == null)
{
return;
}
foreach(DataGridColumn col in dg.Columns)
{
if(this.lblUiView.Text == UserView.User.ToString())
{
if(col.HeaderText == "Salary" || col.HeaderText == "SS#")
{
col.Visible = false;
}
}
else if(this.lblUiView.Text == UserView.Admin.ToString())
{
if(col.HeaderText == "Salary" || col.HeaderText == "SS#")
{
col.Visible = true;
}
}
}
}
Below, is a more simplistic version of the HideShowColumns
. I removed the code related to my example solution so you can get a real clear view of the example. As you can see, it is a very simple solution. The code below will hide a column with a HeaderText
of "ExampleColumn".
private void HideShowColumns(DataGrid dg)
{
if(dg == null)
{
return;
}
foreach(DataGridColumn col in dg.Columns)
{
if(col.HeaderText == "ExampleColumn")
{
col.Visible = false;
}
}
}
DataGrid's HTML
For my example, I added the HeaderText
for each of the columns in the HTML. You could also set this in the WebPage's code-behind class.
<asp:datagrid id=dgExample AutoGenerateColumns="False" runat="server">
<ALTERNATINGITEMSTYLE BackColor="LightSteelBlue">
</ALTERNATINGITEMSTYLE>
<headERSTYLE BackColor="RoyalBlue" HorizontalAlign="Center"></headERSTYLE>
<COLUMNS>
<asp:boundcolumn HeaderText="Name" DataField="Name"></asp:boundcolumn>
<asp:boundcolumn HeaderText="Title" DataField="Title"></asp:boundcolumn>
<asp:boundcolumn HeaderText="Phone" DataField="Phone"></asp:boundcolumn>
<asp:boundcolumn HeaderText="Email" DataField="Email"></asp:boundcolumn>
<asp:boundcolumn HeaderText="Salary" DataField="Salary"></asp:boundcolumn>
<asp:boundcolumn HeaderText="SS#" DataField="SSNum"></asp:boundcolumn>
</COLUMNS>
</asp:datagrid>
Complete Code-Behind Class
I am including the code for those of you who do not want to download the solution. This will provide you with a better understanding of the provided solution. Here are a few things to note:
The Populate
DataGrid method utilizes the GetUsers
method in the UsersFacade
. This retrieves a collection of UserDTO
s. In my example, I do not access a database, I just pre-populate the collection and return it. In a real application, this would access a database or an XML file.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace DgColWebApp
{
public class DgColVisibility : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button btnUser;
protected System.Web.UI.WebControls.DataGrid dgExample;
protected System.Web.UI.WebControls.Button btnAdminView;
protected System.Web.UI.WebControls.Label lblUiView;
private UserFacade userFacade = new UserFacade();
private enum UserView{User, Admin};
private void Page_Load(object sender, System.EventArgs e)
{
if(!this.IsPostBack)
{
this.lblUiView.Text = UserView.User.ToString();
this.PopulateGrid();
}
}
private void PopulateGrid()
{
UserDTO[] users = userFacade.GetUsers();
if(users == null)
{
return;
}
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Title");
dt.Columns.Add("Email");
dt.Columns.Add("Phone");
dt.Columns.Add("Salary");
dt.Columns.Add("SsNum");
foreach(UserDTO user in users)
{
DataRow dr = dt.NewRow();
dr["Name"] = user.Name;
dr["Title"] = user.Title;
dr["Email"] = user.Email;
dr["Phone"] = user.Phone;
dr["Salary"] = user.Salary;
dr["SsNum"] = user.SsNum;
dt.Rows.Add(dr);
}
this.BindDataGrid(dt);
this.HideShowColumns(this.dgExample);
}
private void BindDataGrid(DataTable dt)
{
DataView dv = dt.DefaultView;
this.dgExample.DataSource = dv;
this.dgExample.DataBind();
}
private void HideShowColumns(DataGrid dg)
{
if(dg == null)
{
return;
}
foreach(DataGridColumn col in dg.Columns)
{
if(this.lblUiView.Text == UserView.User.ToString())
{
if(col.HeaderText == "Salary" || col.HeaderText == "SS#")
{
col.Visible = false;
}
}
else if(this.lblUiView.Text == UserView.Admin.ToString())
{
if(col.HeaderText == "Salary" || col.HeaderText == "SS#")
{
col.Visible = true;
}
}
}
}
private void btnUser_Click(object sender, System.EventArgs e)
{
this.lblUiView.Text = UserView.User.ToString();
this.PopulateGrid();
}
private void btnAdminView_Click(object sender, System.EventArgs e)
{
this.lblUiView.Text = UserView.Admin.ToString();
this.PopulateGrid();
}
}
}
Screen Shots
Below is an example of the grid with alternate views. One view is the User View, which has a few columns hidden. The other view is the Admin View, which displays all columns.
User View (Columns Hidden)
Admin View (All Columns Visible)
Conclusion
The problem of referencing a column by index can become a nightmare. As you can see, there is a simple solution to this problem.
Note: This example will not work if you have AutoGenerateColumns = true;
.