Repeater and Collapsible Panel Extender - c#

I am trying to bind a grid view into a repeater for collapsible panel extender body. Here is the code:
<!-- Collapsible panel extender body -->
<asp:Panel ID="pBody1" runat="server" CssClass="cpBody">
<asp:Label ID="lblBodyText1" runat="server" />
<asp:Repeater ID="Repeater2" runat="server" OnItemDataBound="Repeater2_ItemDataBound">
<ItemTemplate>
<asp:GridView ID="gvProduct" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="id" HeaderText="ID" />
<asp:BoundField DataField="name" HeaderText="Name" />
<asp:BoundField DataField="categoryName" HeaderText="Category" />
<asp:BoundField DataField="inventoryQuantity" HeaderText="Quantity" />
</Columns>
</asp:GridView>
</ItemTemplate>
</asp:Repeater>
</asp:Panel>
And from the code behind, I am trying to loop thru the list to get category name. Then, I get all the products based on category name and display them in gridview.
protected void Repeater2_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// This event is raised for the header, the footer, separators, and items.
//Execute the following logic for Items and Alternating Items.
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
for (int count = 0; count < categoryList.Count; count++)
{
string category = categoryList[count].categoryName;
List<ProductPacking> prodList = new List<ProductPacking>();
prodList = packBLL.getAllProductByCategory(category);
gvProduct.DataSource = prodList;
gvProduct.DataBind();
}
}
}
However, it told me that gvProduct does not exist in current context. I wonder how can I get the components inside a repeater? Or am I doing in the wrong way?
Updated Portion.
This is how I bind the header for category name. And I am using another repeater:
<asp:Label ID="lblCategory" Text='<%# DataBinder.Eval(Container.DataItem, "categoryName") %>' runat="server" />
And from the code behind, at the page load, I get all the category:
if (!IsPostBack)
{
//Get all category and bind to repeater to loop
categoryList = packBLL.getAllCategory();
Repeater1.DataSource = categoryList;
Repeater1.DataBind();
}
And for repeater2 which shows the product in each category, I edited it to become like this:
protected void Repeater2_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// This event is raised for the header, the footer, separators, and items.
string category = e.Item.FindControl("categoryName").ToString();
//Execute the following logic for Items and Alternating Items.
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
GridView gv = (GridView)e.Item.FindControl("gvProduct");
if (gv != null)
{
List<ProductPacking> prodList = new List<ProductPacking>();
prodList = packBLL.getAllProductByCategory(category);
DataRowView drv = (DataRowView)e.Item.DataItem;
gv.DataSource = prodList;
gv.DataBind();
}
}
}
However, when I expand the extender, nothing shows up.

If I remember right, you need to use FindControl to access controls that are part of templates, like
GridView oGV = e.Item.FindControl ( "gvProducts" ) as GridView;
You cannot refer to the GridView as gvProducts because there's no single GridView control with that name - a different instance (with a different name) is created for each data item from the template. You need the instance for the current row.
Here's an MSDN example that shows how to access a control during data binding (the example uses a Label).

Related

ItemDataBound in A Datalist in ASP.NET

After reading Formatting the DataList and Repeater Based Upon Data (C#) on Microsoft Website I found the following code sample.
protected void ItemDataBoundFormattingExample_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
// Programmatically reference the ProductsRow instance bound
// to this DataListItem
Northwind.ProductsRow product =
(Northwind.ProductsRow)((System.Data.DataRowView)e.Item.DataItem).Row;
// See if the UnitPrice is not NULL and less than $20.00
if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
{
// TODO: Highlight the product's name and price
}
}
}
However in the above I would like to know where Northwind.ProductsRow product is coming from. Is it from the Northwind database name or somewhere else.
this is a great question, and like some time travel movie, I REALLY WISH someone had and did explain how this works. You note that sometimes the "data source" of the datalist works, and sometimes it does not, and why is this so???
So, the data source comes from WHEN the control was "binded" or spoon fed the data source.
So, on page load, there is most likly some code that set-up and "binds" the data control. Or, it might be that a sqldatasource was dropped into the web page, but AGAIN, either way?
The page load will then trigger the row data bound event.
(ItemDataBound).
So, first BIG tip:
The e.Item.DataItem used IS ONLY available DURING the data bind process. That quite much means at data bind time and the ItemDataBound event.
So, WHEN you shove a data source INTO the GridView, Datalist, ListView, repeater etc controls? And use the data bound event (the name varies a wee bit, bu they all do the same thing), then the DataItemView is ONLY available DURING the row data bind process and hence you are 100% free to use that data source DURING the data bind event - BUT NOT AFTER!!!!!
After, binding has occured, you find that the the dataitem (and control datasoruce is NOW null!!!!). This is VERY different then desktop versions of such controls in .net (in desktop land, you actually can get/use/see the ACTUAL object used for each row!!! - and they persist!!!!
In web land, that data source is converted to a DataRowView.
However, what is the basic knowledge here?
Well, it means that your data control does NOT have to display or hide all of the columns from the database, but you ARE STILL FREE to use those additional columns for things like tax calculations, or for formatting controls based on OTHER columns that you have in the datasource BUT ARE NOT DISPLAYED!!!
And you see BOATLOADS of examples posted where people use hidden fields and all kinds of tricks, and they did that because they DID NOT KNOW the above!!!
Now, it not clear if you want to use a "datalist" control. They tend to be good for say one reocrd, or say several records in a "card like" view - not a table like layout.
So, for a table like layout, I suggest using ListView (most flexible), or for simple, and not too fancy, then use GridView.
But, DataList, listView, GridView, Repeater ? They all of this Row bound (or Item bound) event (they all are VERY close named).
And as noted, JUST like your question, in most cases this event can be used for addtional formatting.
Lets do this with a GridView - (since it easy).
So, say we have a grid of hotel names, but I want to highlight in say blue color ONLY hotels that are active. But I ALSO do NOT want to display the "active" column from the data base in that grid.
So, say this simple markup:
<style> .MyCenter {text-align:center;}</style>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" cssclass="table" OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" ItemStyle-Width="120px" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="View" >
<HeaderStyle CssClass="MyCenter"/>
<ItemStyle CssClass="MyCenter" />
<ItemTemplate>
<asp:Button ID="bView" runat="server" Text="View" CssClass="btn" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Now, our code to load, we have this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL,conn))
{
conn.Open();
DataTable rstData = new DataTable();
rstData.Load(cmdSQL.ExecuteReader());
GridView1.DataSource = rstData;
GridView1.DataBind();
}
}
}
And we now have this:
So, lets use the ItemDataBound event (RowdataBound for Gridview) to highlight the Hotel name and descrption ONLY for Hotels that are active. As noted, we do NOT display "Active" column in the gridview, but with Row data bound event, we still have use of the FULL row.
So, we can add this code to the Row data bound event.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// get the full data row used for binding
DataRowView OneRow = e.Row.DataItem as DataRowView;
// lets highlist the hotel name + description
if ((bool)OneRow["Active"])
{
e.Row.Cells[3].BackColor = System.Drawing.Color.LightSteelBlue;
e.Row.Cells[4].BackColor = System.Drawing.Color.LightSteelBlue;
}
// that button is not centered "vertical", so lets do that
Button btn = e.Row.FindControl("bView") as Button;
DataControlFieldCell g = btn.Parent as DataControlFieldCell;
g.Style.Add("vertical-align", "middle");
}
}
And now we we get this:
So, what about the view item click? For that we could use a datalist as you have, and we could then hide the grid, display the datalist, and we would be quite much on our way with a grid to edit items, then right?
Coffee break - I'll be back in a bit to add the view + datalist to see/view/edit one item.
Ok, part 2 - using a datalist to display above click
Ok, so lets drop in a data list - with a div area (to hide and show).
So, ok, now our data list we drop in.
<div id="MyEditArea" runat="server" style="width:44%;margin-left:35px;padding:8px;border:solid;display:none">
<asp:Datalist ID="DataList1" runat="server" DataKeyField="ID" >
<ItemTemplate>
<style>
.iForm label {display:inline-block;width:95px}
.iForm input {border-radius:8px;border-width:1px;margin-bottom:10px}
.iForm textarea {border-radius:8px;border-width:1px;margin-bottom:10px}
.iForm input[type=checkbox] {margin-right:6px}
</style>
<div style="float:left" class="iForm">
<label>HotelName</label>
<asp:TextBox ID="txtHotel" runat="server" Text='<%# Eval("HotelName") %>' width="280" /> <br />
<label>First Name</label>
<asp:TextBox ID="tFN" runat="server" Text='<%# Eval("FirstName") %>' Width="140" /> <br />
<label>Last Name</label>
<asp:TextBox ID="tLN" runat="server" Text='<%# Eval("LastName") %>' Width="140" /> <br />
<label>City</label>
<asp:TextBox ID="tCity" runat="server" Text='<%# Eval("City") %>' Width="140" /> <br />
<label>Province</label><asp:TextBox ID="tProvince" runat="server" Text='<%# Eval("Province") %>'
f="Province" Width="75"></asp:TextBox> <br />
</div>
<div style="float:left;margin-left:20px;width:420px " class="iForm">
<label>Description</label> <br />
<asp:TextBox ID="txtNotes" runat="server" Width="400" TextMode="MultiLine"
Height="150px" Text='<%# Eval("Description") %>' ></asp:TextBox> <br />
<asp:CheckBox ID="chkActive" Checked='<%# Eval("Active") %>' Text=" Active" runat="server" TextAlign="Right" />
<asp:CheckBox ID="chkBalcony" Checked='<%# Eval("Balcony") %>' Text=" Has Balcony" runat="server" TextAlign="Right" />
<asp:CheckBox ID="chkSmoking" Checked='<%# Eval("Smoking") %>' Text=" Smoking Area" runat="server" TextAlign="Right" />
</div>
<div style="clear:both"></div>
<div style="float:left" class="iForm">
<asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn" />
<asp:Button ID="cmdCancel" runat="server" Text="Cancel" CssClass="btn" style="margin-left:10px" />
</ItemTemplate>
</asp:Datalist>
And now our button click for the grid view - to display that one data list control + data.
Hum, started writing some code routine, so lets clean this up a bit.
Ok, so we now have this to load + format the gridview.
void LoadGrid()
{
GridView1.DataSource = MyRst("SELECT * FROM tblHotelsA ORDER BY HotelName");
GridView1.DataBind();
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// get the full data row used for binding
DataRowView OneRow = e.Row.DataItem as DataRowView;
// lets highlist the hotel name + description
if ((bool)OneRow["Active"])
{
e.Row.Cells[3].BackColor = System.Drawing.Color.LightSteelBlue;
e.Row.Cells[4].BackColor = System.Drawing.Color.LightSteelBlue;
}
// button is not centered "vertical", so lets do that
Button btn = e.Row.FindControl("bView") as Button;
DataControlFieldCell g = btn.Parent as DataControlFieldCell;
g.Style.Add("vertical-align", "middle");
}
}
void CenterControl(Control c)
{
DataControlFieldCell g = c.Parent as DataControlFieldCell;
g.Style.Add("vertical-align", "middle");
}
public DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
And for the button click on the grid, we have this now:
protected void bView_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
GridViewRow gRow = btn.NamingContainer as GridViewRow;
int? PKID = GridView1.DataKeys[gRow.RowIndex]["ID"] as int?;
// Now load our datalist
string strSQL = "SELECT * from tblHotelsA WHERE ID = " + PKID;
DataList1.DataSource = MyRst(strSQL);
DataList1.DataBind();
// hide grid, show edit area
GridView1.Style.Add("display", "none");
MyEditArea.Style.Add("display", "normal");
}
So, now when we click on a row, we hide grid, show our data list control, and we now see/have this:
And just like the grid view, lets highlight the hotelname and description as light grey. Once again, we now use the data list row data bound event.
Say, this:
Note how we don't use .cells for the data list, but have to use find control.
protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)
{
if ( (e.Item.ItemType == ListItemType.Item) |
e.Item.ItemType == ListItemType.AlternatingItem)
{
DataRowView gData = e.Item.DataItem as DataRowView;
if ((bool)gData["Active"])
{
TextBox txtHotel = e.Item.FindControl("txtHotel") as TextBox;
txtHotel.BackColor = System.Drawing.Color.LightSteelBlue;
TextBox txtDescript = e.Item.FindControl("txtNotes") as TextBox;
txtDescript.BackColor = System.Drawing.Color.LightSteelBlue;
}
}
}
And, you do have to check for item, and "alternating" item.
But, now, when we click on a grid row, we get this:

Telerik RadGrid row data to populate GridEditableItem column

I have a telerik radgrid with a hyperlink in one of the columns in edit mode. I want to have the text of the hyperlink set to the page title of the page it links to without creating a hidden field for this. I get this title from a database call which I pass the ID of the current row in the grid that is being edited. Since the ItemDataBound method always does the binding of the GridEditableItem before the actual row itself, the MasterTableView does not contain the ID I need until the next iteration.
The ugly solution I came up with was to keep a reference to the hyperlink and populate it on the very next iteration when the ID is now availible on the grid.
I seem to think there is a better solution!
protected void grid_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item is GridEditableItem && e.Item.IsInEditMode)
{
link = ((e.Item as GridEditableItem)["myHyperlink"].Controls[1] as HyperLink);
go1 = true;
}
if(go2)
{
string myID = grid.MasterTableView.Items[grid.Items.Count - 1].GetDataKeyValue("myID").ToString();
string pageId= PoolAgent.getPageId(Int32.Parse(myID));
link.Text = pageId;
go2 = false;
go1 = false;
}
if (go1)
go2 = true;
aspx:
<telerik:GridBoundColumn DataField="myID" UniqueName="myID" HeaderText="ID" ReadOnly="true">
</telerik:GridBoundColumn>
<telerik:GridTemplateColumn EditFormColumnIndex="2" UniqueName="myHyperlink" HeaderText="Link:" ItemStyle-HorizontalAlign="Center" Display="False" >
<ItemTemplate>
</ItemTemplate>
<EditItemTemplate>
<asp:Hyperlink ID="KeyManagerLink" Runat="server" NavigateUrl='' onclick="popupwindow(this.href, 'popupwindow', 1150, 500); return false;"></asp:Hyperlink>
</EditItemTemplate>
</telerik:GridTemplateColumn>

TextBox in gridview not retrieving data

I am having some problem with the grid view. I have a grid view with column of 5. When I select add item from top, the grid view at the bottom will be refresh. At the same time, it is retrieving some data from the database and display it in the text box in grid view. Here is my button action event method:
protected void lbnAdd_Click(object sender, EventArgs e)
{
List<ProductPacking> prodVariantDetail = new List<ProductPacking>();
// get the last product variant IDs from ViewState
prodVariantIDList = this.SelectedVariantDetailIDs;
foreach (RepeaterItem ri in Repeater1.Items)
{
GridView gvProduct = (GridView)ri.FindControl("gvProduct");
foreach (GridViewRow gr in gvProduct.Rows)
{
CheckBox cb = (CheckBox)gr.FindControl("cbCheckRow");
if (cb.Checked)
{
// add the corresponding DataKey to idList
prodVariantIDList.Add(gvProduct.DataKeys[gr.RowIndex].Value.ToString());
}
}
}
for (int i = 0; i < prodVariantIDList.Count; i++)
{
prodVariantDetail.Add(prodPackBLL.getProdVariantDetailByID(prodVariantIDList[i]));
foreach (GridViewRow gr in gvFinalised.Rows)
{
//Get the product packaging quantity by productName
string name = gr.Cells[2].Text;
int productQuantity = packBLL.getProductQuantityByName(name);
TextBox tb = (TextBox)gr.Cells[5].FindControl("tbQuantity");
tb.Text = productQuantity.ToString();
}
}
gvFinalised.DataSource = prodVariantDetail;
gvFinalised.DataBind();
// save prodVariantIDList to ViewState
this.SelectedVariantDetailIDs = prodVariantIDList;
}
However, it just keep returning me 0. I did check the SQL statement, all returning me the correct values. Is there any way to fix this?
Thanks in advance.
EDIT
<asp:GridView ID="gvFinalised" runat="server" AutoGenerateColumns="False" CellPadding="2" ForeColor="#333333" GridLines="None" Width="740px" DataKeyNames="id">
<Columns>
<asp:BoundField DataField="id" HeaderText="ID" ItemStyle-Width="50px" />
<asp:BoundField DataField="categoryName" HeaderText="Category" ItemStyle-Width="100px" />
<asp:BoundField DataField="name" HeaderText="Product" ItemStyle-Width="350px" />
<asp:BoundField DataField="inventoryQuantity" HeaderText="Stock" ItemStyle-Width="100px" />
<asp:BoundField DataField="unitQuantity" HeaderText="Unit" ItemStyle-Width="100px" />
<asp:TemplateField HeaderText="Quantity" ItemStyle-HorizontalAlign="Center" ItemStyle-Width="200px">
<ItemTemplate>
<asp:TextBox ID="tbQuantity" runat="server" Width="40" Text="0" OnTextChanged="tbQuantity_TextChanged" AutoPostBack="true" />
<asp:Label ID="lblCheckAmount" runat="server" ForeColor="#a94442"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The problem is you loop through gvFinalised rows before binding the data, so whatever you do inside the looping will be overwritten when you call gvFinalised.DataBind().
Quick solution
Move this:
foreach (GridViewRow gr in gvFinalised.Rows)
{
//Get the product packaging quantity by productName
string name = gr.Cells[2].Text;
int productQuantity = packBLL.getProductQuantityByName(name);
TextBox tb = (TextBox)gr.Cells[5].FindControl("tbQuantity");
tb.Text = productQuantity.ToString();
}
after this:
gvFinalised.DataSource = prodVariantDetail;
gvFinalised.DataBind();
Alternative Solution
As mentioned by #SutharMonil below, there's an alternative way to do this using RowDataBound event. First set OnRowDataBound property to the event handler name in aspx code, let's say the name is gvFinalised_RowDataBound:
<asp:GridView ID="gvFinalised" runat="server" AutoGenerateColumns="False" CellPadding="2"
ForeColor="#333333" GridLines="None" Width="740px" DataKeyNames="id" OnRowDataBound="gvFinalised_RowDataBound">
then in code behind, remove the following code:
foreach (GridViewRow gr in gvFinalised.Rows)
{
//Get the product packaging quantity by productName
string name = gr.Cells[2].Text;
int productQuantity = packBLL.getProductQuantityByName(name);
TextBox tb = (TextBox)gr.Cells[5].FindControl("tbQuantity");
tb.Text = productQuantity.ToString();
}
and add the following code:
protected void gvFinalised_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Display the company name in italics.
e.Row.Cells[1].Text = "<i>" + e.Row.Cells[1].Text + "</i>";
//Get the product packaging quantity by productName
string name = e.Row.Cells[2].Text;
int productQuantity = packBLL.getProductQuantityByName(name);
TextBox tb = (TextBox)e.Row.Cells[5].FindControl("tbQuantity");
tb.Text = productQuantity.ToString();
}
}
This way the quantity textbox inside gvFinalised will always be updated whenever gvFinalised.DataBind() is called.

Dynamic control Viewstate

I am now stuck. After spending ages trying to maintain dynamically added linkbutton or label to a gridview it seems I am overwriting a checkbox state on post back.
As stated I am dynamically adding either a linkbutton or a label to a place holder in a gridview with the following:
protected void LedgerGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int index = e.Row.RowIndex;
if (items[index].noteID > 0)
{
PlaceHolder label = (PlaceHolder)e.Row.FindControl("HasPrevious");
LinkButton link = new LinkButton();
link.CommandName = "LinkCommand";
link.Command += new CommandEventHandler(link_Command);
link.Text = "Yes";
link.ID = index.ToString();
label.Controls.Add(link);
}
else
{
PlaceHolder label = (PlaceHolder)e.Row.FindControl("HasPrevious");
Label noNote = new Label();
noNote.Text = "No";
label.Controls.Add(noNote);
}
Here is the gridview:
<asp:GridView runat="server" ID="LedgerGrid" AutoGenerateColumns="false"
onselectedindexchanged="LedgerGrid_SelectedIndexChanged"
onrowdatabound="LedgerGrid_RowDataBound" onrowcommand="LedgerGrid_RowCommand"
>
<Columns>
<asp:TemplateField HeaderText="Notes">
<ItemTemplate>
<asp:PlaceHolder ID="HasPrevious" runat="server"></asp:PlaceHolder>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Invoice Date" DataField="invoicedate" DataFormatString="{0:d}" />
<asp:BoundField HeaderText="Invoice" DataField="invoice" />
<asp:BoundField HeaderText="Fee Debt" DataField="Fee_Debt" DataFormatString="{0:C}" />
<asp:BoundField HeaderText="Cost Debt" DataField="Cost_Debt" DataFormatString="{0:C}" />
<asp:BoundField HeaderText="VAT Debt" DataField="VAT_Debt" DataFormatString="{0:C}" />
<asp:BoundField HeaderText="Total Debt" DataField="Total_Debt" DataFormatString="{0:C}" />
<asp:BoundField HeaderText="Client Code" DataField="ClientCode" />
<asp:ButtonField HeaderText="Matter Number" DataTextField="matternumber" CommandName="ViewMatter" />
<asp:BoundField HeaderText="Decription" DataField="matterdescription" />
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="AddInvoiceCheck" runat="server" Enabled="true" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
To make sure that my link button command works I am rebuilding the gridview as I would in the Page_load. Here is the page load:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string clientCode = Server.HtmlEncode(Request.QueryString["clientcode"]);
items = DataAccess.DataAccess.GetLedgerDetails(clientCode);
ViewState["LedgerItems"] = items;
ViewState["clientcode"] = clientCode;
LedgerGrid.DataSource = items;
LedgerGrid.DataBind();
LedgerClientObject clientDetails = DataAccess.DataAccess.GetClientDetails(clientCode);
ClientCodeLabel.Text = string.Format("Group Code: {0}", clientDetails.GroupCode);
ClientNameLabel.Text = string.Format("Client Name: {0}", clientDetails.ClientName);
ClientCodeFilter.DataSource = clientDetails.ClientCodes;
ClientCodeFilter.DataBind();
}
}
To maintain the dynamically added controls on post back I am calling the following:
protected void Page_PreLoad(object sender, EventArgs e)
{
if (IsPostBack)
{
items = (List<LedgerItem>)ViewState["LedgerItems"];
LedgerGrid.DataSource = items;
LedgerGrid.DataBind();
}
}
Of course it now seems that by using this method I am overwriting the state of the check-box gridview column. Am I approaching this all wrong? I would like to be able to use the viewstate to maintain the set up of my dynamically added controls to the gridview. Is there a way I can access the state of the checkbox control form gridview before/after I reload the gridview in PreLoad event?
I am checking the state of my checkbox column with a button click as follows:
protected void Unnamed1_Click(object sender, EventArgs e)
{
NoteModel note = new NoteModel();
for (int i = 0; i < LedgerGrid.Rows.Count; i++)
{
int invoice = Convert.ToInt32(LedgerGrid.Rows[i].Cells[2].Text);
CheckBox check = (CheckBox)LedgerGrid.Rows[i].FindControl("AddInvoiceCheck");
if (check.Checked)
{
note.invoices.Add(invoice);
}
}
if (note.invoices == null)
{
string clientcode = (string)ViewState["clientcode"];
ViewState["InvoiceError"] = 1;
Response.Redirect(string.Format("Ledger.aspx?clientcode={0}", clientcode));
}
else
{
string clientcode = (string)ViewState["clientcode"];
Session["NoteObject"] = note;
Response.Redirect(string.Format("AddNote.aspx?cc={0}", clientcode));
}
}
Whenever I iterate over the checkbox controls in the gridview they are all unchecked e.g overwritten by my PreLoad code!!!
In the end I decided not to use dynamically created controls. Instead I added a buttonfield to the grid view. In my rowdatabound event I then set the visibility of the button to false if it does meet my criteria. This way view state is maintained as i do not need to create control on post back.
Seems with webforms that avoiding dynamic controls where possible is the best bet. I would still like to know which event to tap into to override viewstate re-instating controls?

Adding Querystring Parameter to GridView ItemTemplate

I have a gridview with a hyperlink in first column. Upon clicking the hyperlink, the user is redirected to Vendor.aspx. Now, I need to pass the consumer id (of the clicked row) as a query string to the Vendor.aspx.
What is the best method to achieve it? Is there a way in which we can handle it using markup code only?
<asp:GridView ID="grdConsumers" runat="server" AutoGenerateColumns="False"
EnableViewState="True" >
<Columns>
<asp:TemplateField HeaderText="ConsumerID" SortExpression="ConsumerID" >
<ItemTemplate>
<asp:HyperLink ID="lnkConsumerID" href="Vendor.aspx" runat="server"><%# Eval("ConsumerID")%></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Status" DataField="Status" SortExpression="Status"></asp:BoundField>
</Columns>
</asp:GridView>
READINGS:
Set Gridview DataNavigateUrlFormatString Dynamically inside User Control(ASCX)
How do I add "&Source" to DataNavigateUrlFormatString?
Select row in GridView with JavaScript
How to bind the URL of a GridView HyperLinkField when the bound value contains a colon?
asp.net gridview DataNavigateUrlFormatString from DataSource
Try using the DataNavigateUrlFormatString
<ItemTemplate>
<asp:HyperLinkField DataNavigateUrlFields="ConsumerID" DataTextField="ConsumerID" DataNavigateUrlFormatString="Vendor.aspx?id={0}" />
</ItemTemplate>
... it will spare you Eval() and the problem with single/double quotes when putting it inside your href.
You can substitute the DataTextField if you like - I just put the ConsumerID there to be consistent with your example.
Rewrite your hyperlink in gridview in .aspx file like this:
<asp:HyperLink ID="lnkConsumerID" runat="server" Text='<%# Eval("ConsumerID")%>' />
Then in code-behind create a RowDataBound event handler:
protected void grdConsumers_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType != DataControlRowType.DataRow) return;
var hlnkhlnk = (HyperLink)e.Row.FindControl("lnkConsumerID");
if (hlnkhlnk != null)
{
hlnkhlnk.NavigateUrl = "Vendor.aspx" + "?Consumer ID=" + hlnkhlnk.Text;
}
}
Hope it helps.
You can do same using at Grid view Item Data Bound Event
protected void grdConsumers_ItemDataBound(object sender,DataGridItemEventArgs e)
{
if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// Get your consumerId here
((HyperLink)e.Item.FindControl("Edit")).NavigateUrl = "Vendor.aspx?id=" + consumerId
}
}

Categories

Resources