Getting a column name in a Repeater in OnItemCreated - asp.net

I am working on a Repeater that reads from a table with a layout something like:
string Title
string Location
bool Water
bool Sewer
bool Picnic_Table
bool On_Beach
...
I am creating a list of amenities for each "Title" so I need to loop through the columns and get a list of amenities for each Title (or site). Optimally, I have a loop to go through the list. Something like
for each column
if column is not Title or Location
Append to StringBuilder "column name"
How do I get that column name to do the comparisons?

Here's how to get the column name in the OnItemCreated event of the Repeater control:
protected void rptOnItemCreated_OnItemCreated(object sender, RepeaterItemEventArgs e)
{
string columnName = string.Empty;
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
DataRowView drv = (DataRowView)e.Item.DataItem;
DataRow dr = drv.Row;
foreach (DataColumn dc in dr.Table.Columns)
{
// Do what you want with the column name
columnName = dc.ColumnName;
}
}
}

Repeater is not a table-based control, so that's going to be hard from the server-side. What you can do is programmably create a table, or use the Grid control. Or, try to make the table a server-side control, and see if that works well with the repeater (I don't think it will). Or, if you can say ignore the first two columns, make the table row within the repeater item a server-side row as in , and use FindControl to find the item and do something with it. You would have to work with the cell index though, to show/hide cells within the column.
HTH.

Related

how bind DataList template field in asp.net

i want to bind a label -i created- in Datalist template to col -named "item"-in my dataSource
i used the following code after several trials
DataList2.DataSource = dt; // my DataSource
Label l1 = (Label)DataList2.FindControl("itemLabel");
l1.Text = dt.Rows[0]["item"].ToString();
DataList2.DataBind();
i got the following error at line '3' i am looking for the right expression
Object reference not set to an instance of an object.
any help would be appreciated..
The label is null since it's NamingConainer(used for FindControl) is not the DataList but one of it's DataListItems (a DataList is used for multiple items).
So you need to DataBind it first, then you can handle it's ItemDataBound event. There you are able to find the label and the underlying DataItem.
void Item_Bound(Object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
// Retrieve the Label control in the current DataListItem.
Label itemLabel= (Label)e.Item.FindControl("itemLabel");
DataRow row = ((DataRowView)e.Item.DataItem).Row;
String item = row.Field<string>("item");
itemLabel.Text = item;
}
}

How to store cell value of an Asp.Net GridView row on click in a C# variable

I am having a GridView in my page , I want that when a particular row is clicked I want the cell value of that particular row.Currently I get that that value by using something like this ,
protected void SearchRecordGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Attributes.Add("onclick", "location='ModifyCustomerByCategory.aspx?ApplicationNo=" + e.Row.Cells[0].Text + "'");
}
}
Currently I am passing that value as a parameter to the page , can any body tell how can I store that value in a variable or , atleast on click I assign it to a hidden field.
Thanks for any suggestions.
Try this link.
It runs through everything you will need, and on the gridview selectedindexchanged event you can reference the value with GridView.SelectedRow.Cells[0].Text or the control containing the value Gridview.SelectedRow.FindControl("[Control Name]")
In row data bound simply save that value and use it
int appno = CInt(e.Row.Cells[0].Text)
and if you want to use this value to next page
int appno = CInt(Request.Querystring("ApplicationNo"))

How to hide columns in an ASP.NET GridView with auto-generated columns?

GridView1.Columns.Count is always zero even SqlDataSource1.DataBind();
But Grid is ok
I can do
for (int i = 0; i < GridView1.HeaderRow.Cells.Count;i++)
I rename request headers here
but
GridView1.Columns[i].Visible = false;
I can't use it because of GridView1.Columns.Count is 0.
So how can I hide them ?
Try putting the e.Row.Cells[0].Visible = false; inside the RowCreated event of your grid.
protected void bla_RowCreated(object sender, GridViewRowEventArgs e)
{
e.Row.Cells[0].Visible = false; // hides the first column
}
This way it auto-hides the whole column.
You don't have access to the generated columns through grid.Columns[i] in your gridview's DataBound event.
The Columns collection is only populated when AutoGenerateColumns=false, and you manually generate the columns yourself.
A nice work-around for this is to dynamically populate the Columns collection yourself, before setting the DataSource property and calling DataBind().
I have a function that manually adds the columns based on the contents of the DataTable that I want to display. Once I have done that (and then set the DataSource and called DataBind(), I can use the Columns collection and the Count value is correct, and I can turn the column visibility on and off as I initially wanted to.
static void AddColumnsToGridView(GridView gv, DataTable table)
{
foreach (DataColumn column in table.Columns)
{
BoundField field = new BoundField();
field.DataField = column.ColumnName;
field.HeaderText = column.ColumnName;
gv.Columns.Add(field);
}
}
Note: This solution only works if your GridView columns are known ahead of time.
It sounds like you're using a GridView with AutoGenerateColumns=true, which is the default. I recommend setting AutoGenerateColumns=false and adding the columns manually:
<asp:GridView runat="server" ID="MyGridView"
AutoGenerateColumns="false" DataSourceID="MySqlDataSource">
<Columns>
<asp:BoundField DataField="Column1" />
<asp:BoundField DataField="Column2" />
<asp:BoundField DataField="Column3" />
</Columns>
</asp:GridView>
And only include a BoundField for each field that you want to be displayed. This will give you the most flexibility in terms of how the data gets displayed.
I was having the same problem - need my GridView control's AutogenerateColumns to be 'true', due to it being bound by a SQL datasource, and thus I needed to hide some columns which must not be displayed in the GridView control.
The way to accomplish this is to add some code to your GridView's '_RowDataBound' event, such as this (let's assume your GridView's ID is = 'MyGridView'):
protected void MyGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Cells[<index_of_cell>].Visible = false;
}
}
That'll do the trick just fine ;-)
You have to perform the GridView1.Columns[i].Visible = false; after the grid has been databound.
Try this to hide columns in an ASP.NET GridView with auto-generated columns, both RowDataBound/RowCreated work too.
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Or _
e.Row.RowType = DataControlRowType.Header Then // apply to datarow and header
e.Row.Cells(e.Row.Cells.Count - 1).Visible = False // last column
e.Row.Cells(0).Visible = False // first column
End If
End Sub
Protected Sub GridView1_RowCreated(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Or _
e.Row.RowType = DataControlRowType.Header Then
e.Row.Cells(e.Row.Cells.Count - 1).Visible = False
e.Row.Cells(0).Visible = False
End If
End Sub
In the rowdatabound method for 2nd column
GridView gv = (sender as GridView);
gv.HeaderRow.Cells[2].Visible = false;
e.Row.Cells[2].Visible = false;
#nCdy:
index_of_cell should be replaced by an integer, corresponding to the index number of the cell that you wish to hide in the .Cells collection.
For example, suppose that your GridView presents the following columns:
CONTACT NAME | CONTACT NUMBER | CUSTOMERID | ADDRESS LINE 1 | POST CODE
And you want the CUSTOMERID column not to be displayed.
Since collections indexes are 0-based, your CUSTOMERID column's index is..........? That's right, 2!! Very good.
Now... guess what you should put in there, to replace 'index_of_cell'??
As said by others, RowDataBound or RowCreated event should work but if you want to avoid events declaration and put the whole code just below DataBind function call, you can do the following:
GridView1.DataBind()
If GridView1.Rows.Count > 0 Then
GridView1.HeaderRow.Cells(0).Visible = False
For i As Integer = 0 To GridView1.Rows.Count - 1
GridView1.Rows(i).Cells(0).Visible = False
Next
End If
I found Steve Hibbert's response to be very helpful. The problem the OP seemed to be describing is that of an AutoGeneratedColumns on a GridView.
In this instance you can set which columns will be "visible" and which will be hidden when you bind a data table in the code behind.
For example:
A Gridview is on the page as follows.
<asp:GridView ID="gv" runat="server" AutoGenerateColumns="False" >
</asp:GridView>
And then in the code behind a PopulateGridView routine is called during the page load event.
protected void PopulateGridView()
{
DataTable dt = GetDataSource();
gv.DataSource = dt;
foreach (DataColumn col in dt.Columns)
{
BoundField field = new BoundField();
field.DataField = col.ColumnName;
field.HeaderText = col.ColumnName;
if (col.ColumnName.EndsWith("ID"))
{
field.Visible = false;
}
gv.Columns.Add(field);
}
gv.DataBind();
}
In the above the GridView AutoGenerateColumns is set to False and the codebehind is used to create the bound fields. One is obtaining the datasource as a datatable through one's own process which here I labeled GetDataSource(). Then one loops through the columns collection of the datatable. If the column name meets a given criteria, you can set the bound field visible property accordingly. Then you bind the data to the gridview. This is very similar to AutoGenerateColumns="True" but you get to have criteria for the columns. This approach is most useful when the criteria for hiding and un-hiding is based upon the column name.
Similar to accepted answer but allows use of ColumnNames and binds to RowDataBound().
Dictionary<string, int> _headerIndiciesForAbcGridView = null;
protected void abcGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (_headerIndiciesForAbcGridView == null) // builds once per http request
{
int index = 0;
_headerIndiciesForAbcGridView = ((Table)((GridView)sender).Controls[0]).Rows[0].Cells
.Cast<TableCell>()
.ToDictionary(c => c.Text, c => index++);
}
e.Row.Cells[_headerIndiciesForAbcGridView["theColumnName"]].Visible = false;
}
Not sure if it works with RowCreated().
Iterate through the GridView rows and make the cells of your target columns invisible. In this example I want to keeps columns 4-6 visible as is, so we skip those:
foreach (GridViewRow row in yourGridView.Rows)
{
for (int i = 0; i < rows.Cells.Count; i++)
{
switch (i)
{
case 4:
case 5:
case 6:
continue;
}
row.Cells[i].Visible = false;
};
};
Then you will need to remove the column headers separately (keep in mind that removing header cells changes the length of the GridView after each removal):
grdReportRole.HeaderRow.Cells.RemoveAt(0);

Modifying data in new columns in a GridView (ASP.net 3.5 newbie)

my problem: how do I populate extra cells in my gridview during the runtime construction of the grid? (these cells are not bound to any datasource and all I want to do is show some custom text)
I have a gridview on my page and I get 2 columns as bound columns from a fixed database - let's call them
id and URL
I've added a couple of extra columns which are not bound to any datafield but I want to populate the cells with some text which is relevant to the id
for e.g. if the row 1 is
12 http://www.something.com
then I want the extra cell to have 'you have visited this 13 times'
12 http://www.something.com 'you have visited this 13 times'
this text comes from some internal processing I do.
What I want to do is to insert this text when the gridview is being constructed at run time..am totally clueless how to do this. I'm sorry if I'm asking a very dumb question..
You can use the OnRowDataBound event of the GridView to get the current DataItem's content and then set the value of your extra column. You could also just get the cell's content. I think using the DataItem is a bit better, but you can do either.
Something like below
protected void MyGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string myValue = e.Row.Cells[0].Text;
e.Row.Cells[3].Text = " you have visited this " + myValue + " times";
-- or --
MyObjectType myData = e.Row.DataItem as MyObjectType ;
Literal litText = e.Row.FindControl("litText") as Literal;
litText.Text = "you have visited this " + myData.PropertyName + " times";
}
}
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.onrowdatabound.aspx
http://www.nikhedonia.com/notebook/entry/how-to-show-some-rows-differently-in-a-gridview/
Any way to manipulate the columns in GridView with AutoGenerateColumns = true?

ASP.Net Grid View rolling total in Gridview

I have seen several tutorials on how to achieve this.
However in my opinion they require a lot of prior knowledge on how to programatically refer to each item.
Does anyone have a link to or can create a relatively basic example of how to achive a running total in the footer for an ASP:Gridview?
This is what I use:
protected void InvoiceGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
var invoice = (Invoice) e.Row.DataItem;
if (e.Row.RowType == DataControlRowType.Header)
{
totalAmt = 0;
}
else if (e.Row.RowType == DataControlRowType.DataRow)
{
totalAmt += invoice.Amount;
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
var amountTotalLabel = (TextBox) e.Row.FindControl("AmountTotalTextBox");
amountTotalLabel.Text = totalAmt.ToString("0.00");
}
}
TotalAmt is protected instance variable on the page. Not sure if it's what you were looking for based on your comment about "programmatic knowledge." But it works and is fairly straight-forward. The gridview is bound to a List<Invoice> in this case.
Add the footer Template and on the RowDataBound, have a global variable to store the summation sum,
At the e.Row.RowType = DataControlRowType.DataRow type do the summation , and # the e.Row.RowType = DataControlRowType.Footer store the vale in the appropriate cell
for further info look # MSDN LINK
This is how I do it. Very easy. You just sum the row that has your numbers in it and place it in the footer.
((Label)GridView.FooterRow.Cells[1].FindControl("your_label")).Text = ds.Tables[0].Compute("sum(Column_name)", "").ToString();
I think the method I use is pretty basic and doesn't require programatically referring to columns in the Gridview, if that's what you mean. That's one of the nice parts is that once you get the back-end functions written, you can add totals to any Gridview by only editing the .aspx file.
In your GridView, make the column like this:
<asp:TemplateField HeaderText="Hours">
<ItemTemplate><%#DisplayAndAddToTotal(Eval("Hours").ToString(), "Hours")%></ItemTemplate>
<FooterTemplate><%#GetTotal("Hours")%></FooterTemplate>
</asp:TemplateField>
The second parameter to DisplayAndAddToTotal can be any string you want as long as you use the same string in GetTotal. I usually just use the field name again though. Here are the two functions used, DisplayAndAddToTotal and GetTotal. They use a Hashtable to store the totals so that it works with any number of columns you want to add up. And they also work with counting the number of "True"s for a Boolean field.
Protected total As Hashtable = New Hashtable()
Protected Function DisplayAndAddToTotal(itemStr As String, type As String) As Double
Dim item As Double
If itemStr = "True" Then
item = 1
ElseIf Not Double.TryParse(itemStr, item) Then
item = 0
End If
If total.ContainsKey(type) Then
total(type) = Double.Parse(total(type).ToString()) + item
Else
total(type) = item
End If
Return item
End Function
Protected Function GetTotal(type As String) As Double
Try
Dim result As Double = Double.Parse(total(type).ToString())
Return result
Catch
Return 0
End Try
End Function

Resources