I have a readymade library(dll) given to me, which has important data, i m able to take that data into Datatable
and successfully displaying it on a GridView
.
Now my further task is the Data what it is displaying in GridView
should be filterable, meaning if i click on any column on a row it should filtered results of similar columns.
This is my GridView Result
HeaderCol1 HeaderCol2 HeaderCol3 HeaderCol4
Name1 Info1 ID1 Time1
Name2 Info2 ID2 Time2
Name1 Info3 ID3 Time3
Name3 Info2 ID4 Time4
Name4 Info4 ID3 Time5
Name5 Info5 ID5 Time5
Now what i want is if i click on Name1 it should show
HeaderCol1 HeaderCol2 HeaderCol3 HeaderCol4
Name1 Info1 ID1 Time1
Name1 Info3 ID3 Time3
And if i click on Info2 it should show
HeaderCol1 HeaderCol2 HeaderCol3 HeaderCol4
Name2 Info2 ID2 Time2
Name3 Info2 ID4 Time4
I think my question is clear now. How can i achieve this? Thanks in advance
So you want to filter a GridView's DataSource
by a value of a cell the user clicked on. These are multiple tasks in one, i'll try to explain all.
The major task is to enable that every cell in the GridView
reacts on a user's click, handling that click-event on serverside and get somehow the value from that cell.
I've used a DataTable
in following example, replace it with your type of datasource. If you need to add custom events/controls to GridViewRows
the best place is RowCreated
since this is called on every postback not only on databinding. Note that you don't have the DataItem
at this stage.
protected void gridView1_RowCreated(Object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
for(int i = 0; i < e.Row.Cells.Count; i++)
{
TableCell cell = e.Row.Cells[i];
cell.ToolTip = "Click to filter by this value";
string js = string.Format("var txt=document.getElementById('{0}');txt.value='{1} {2}';{3}"
, TxtFilter.ClientID, e.Row.RowIndex, i
, ClientScript.GetPostBackClientHyperlink(TxtFilter, null));
cell.Attributes["onclick"] = js;
}
}
}
As you can see i've added the clientside onclick
event to each cell. I'm using a hidden TextBox
(display:none) with AutoPostBack=true
to store the row and cell the user has clicked. Now you're able to handle and process the click event on serverside.
protected void FilterGrid(object sender, EventArgs e)
{
TextBox txtFilter = (TextBox)sender;
string[] parts = txtFilter.Text.Split();
int row = int.Parse(parts[0]);
int col = int.Parse(parts[1]);
gridView1.DataSource = GetData(row, col);
gridView1.DataBind();
}
// replace with your DAL, used a DataTable for testing
private DataTable GetData(int rowIndex = -1, int colIndex = -1)
{
DataTable tblData = getDataSource();
if (rowIndex > -1 && colIndex > -1)
{
var field = tblData.Columns[colIndex];
var row = tblData.Rows[rowIndex];
var value = row[field];
// now use Linq-To-DataSet to filter the table, remember to add 'using System.Linq'
tblData = tblData.AsEnumerable()
.Where(r => !r.IsNull(field) && r[field].Equals(value))
.CopyToDataTable();
}
return tblData;
}
Here's the aspx of my sample page:
<asp:TextBox ID="TxtFilter" runat="server" style="display:none" AutoPostBack="true" OnTextChanged="FilterGrid" />
<asp:GridView ID="gridView1" runat="server" AutoGenerateColumns="False" OnRowCreated="gridView1_RowCreated" >
<Columns>
<asp:TemplateField HeaderText="HeaderCol1">
<ItemTemplate>
<asp:Label ID="LblHeaderCol1" runat="server" Text='<%#Eval("HeaderCol1") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="HeaderCol2">
<ItemTemplate>
<asp:Label ID="LblHeaderCol2" runat="server" Text='<%#Eval("HeaderCol2") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="HeaderCol3">
<ItemTemplate>
<asp:Label ID="LblHeaderCol3" runat="server" Text='<%#Eval("HeaderCol3") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="HeaderCol4">
<ItemTemplate>
<asp:Label ID="LblHeaderCol4" runat="server" Text='<%#Eval("HeaderCol4") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>