Combining a Telerik hyperlinkcolumn and a gridboundcolumn into 1 field - c#

I was able to get part of my answer from another question but cannot find a more specific bit of information that I need to finish.
I am trying to combine 2 fields into 1 like the above question but one of them is a GridHyperLinkColumn. I am using a GridItemDataBound event in the code behind to put 2 fields together like this:
protected void GridItemDataBound(object sender, GridItemEventArgs e) {
if (e.Item is GridDataItem) {
GridDataItem item = (GridDataItem)e.Item;
item["A"].Text = item["A"].Text + " /<br/>" + item["B"].Text;
item["C"].Text = item["C"].Text + " /<br/>" + item["D"].Text;
}
}
My UI shorten down for simplicity looks like this:
<Columns>
<telerik:GridBoundColumn UniqueName="A" DataField="A" />
<telerik:GridBoundColumn UniqueName="B" DataField="B" Visible="false" />
<telerik:GridHyperLinkColumn DataNavigateUrlFields="ID" DataNavigateUrlFormatString="~.aspx?ID={0}" DataTextField="C" Text="{0}" UniqueName="C" />
<telerik:GridBoundColumn UniqueName="D" DataField="D" Visible="false" />
</Columns>
This works well for the first 2 columns that I combine into 1 (A & B).
However suppose item["C"] is a GridHyperLinkColumn. When I try the same code, it only shows / <D value>. Nothing shows up in front of the slash where "C" should be showing.
Is there a different property (instead of .Text) I should use or do I need to do it a different way?

There are a number of ways you could do this. One approach would be to use a template column as show below:
<Columns>
<telerik:GridTemplateColumn HeaderText="A and B">
<ItemTemplate><%# Eval("A") %>/<br /><%# Eval("B") %></ItemTemplate>
</telerik:GridTemplateColumn>
<telerik:GridTemplateColumn HeaderText="B and C">
<ItemTemplate><%# Eval( "C" ) %>/<br /><%# Eval("D") %></ItemTemplate>
</telerik:GridTemplateColumn>
</Columns>
If you're not interested in using a template column, you can get it to work the way you're doing it. The issue is that the GridHyperlinkColumn renders the link as a control (e.g. item["C"].Controls[0]) instead of directly in the Text property. Here is one way to get it to do what you want:
if (e.Item is GridDataItem) {
GridDataItem item = (GridDataItem)e.Item;
item["A"].Text = item["A"].Text + " /<br/>" + item["B"].Text;
Literal lit = new Literal();
lit.Text = " /<br/>" + item["D"].Text;
item["C"].Controls.Add( lit );
}

Related

Calculating total underneath a gridview

I have a gridview that has a quantity and calculated price right next to it. When I change the quantity inside the Gridview, the price changes right away. I want to show total price outside the gridview . I am showing the total price outside the gridview, but the price is not changing dynamically when the quantity and price changes for individual items. Below is the image of what I want. I want to $560 to be displayed and calculated right away as soon as price changes.
Below is my gridview code:
<asp:GridView ID="grdShoppingCart" runat="server" AutoGenerateColumns="false" class="ui-responsive table-stroke ss-table ui-search-result-table" GridLines="None" OnRowDataBound="grdShoppingCart_RowDataBound" >
<Columns>
<asp:BoundField DataField="item" HeaderText="Item" HeaderStyle-Font-Bold="true" ItemStyle-HorizontalAlign="Left" HeaderStyle-HorizontalAlign="Left" ItemStyle-Width="250px" ControlStyle-CssClass="ss-row" />
<asp:TemplateField HeaderText="Description" HeaderStyle-Font-Bold="true" HeaderStyle-HorizontalAlign="Left" ItemStyle-HorizontalAlign="Left" ItemStyle-Width="300px" ControlStyle-CssClass="ss-row" >
<ItemTemplate>
<asp:Label ID="lblDesc" runat="server" Text='<%# Eval("child") %>' /><br />
Requested By: <asp:Label ID="lblDesc1" runat="server" Text='<%# Eval("RequestedBy") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Quantity" HeaderStyle-HorizontalAlign="Left" ItemStyle-HorizontalAlign="Left" ControlStyle-CssClass="ss-row" >
<ItemTemplate>
<asp:TextBox Width="45px" TextMode="Number" ID="txtQuantity" Text='<%#Eval("Quantity") %>' runat="server" AutoPostBack="true" OnTextChanged="txtQuantity_TextChanged" ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Price" HeaderStyle-HorizontalAlign="right" ItemStyle-HorizontalAlign="Right" ItemStyle-Width="100px" ControlStyle-CssClass="ss-row" >
<ItemTemplate>
<asp:Label ID="lblPrice" runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False" HeaderStyle-HorizontalAlign="center" ItemStyle-HorizontalAlign="center" ItemStyle-Width="150px" ControlStyle-CssClass="ss-row" >
<ItemTemplate>
<asp:ImageButton CommandArgument='<%# Eval("recordId") %>' ID="imgbtnDelete" runat="server" ImageUrl="~/Images/delete1.png" CommandName="Delete" ToolTip="Click To Dletee" AlternateText="Click To Dletee"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
his is what I tried to do in my code behind to show the total:
I declared this variable inside my class and put the value of price text box in total variable in rowDatabound
public string total;
protected void grdShoppingCart_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Label lbl = (e.Row.FindControl("lblPrice") as Label);
TextBox tbq = (e.Row.FindControl("txtQuantity") as TextBox);
if(tbq.Text !="")
{
lbl.Text = (Convert.ToInt32(tbq.Text) * 28).ToString();
total= lbl.Text.ToString();
}
}
}
and in the aspx page, I wrote this:
Total: <%=total %>
below is the code that changes the price and quantity:
protected void txtQuantity_TextChanged(object sender, EventArgs e)
{
TextBox changeTextbox = sender as TextBox;
GridViewRow row = (GridViewRow)changeTextbox.NamingContainer;
TextBox tbq = (row.FindControl("txtQuantity") as TextBox);
Label lblPrice = (row.FindControl("lblPrice") as Label);
lblPrice.Text = (Convert.ToInt32(tbq.Text) * 28).ToString();
}
any help will be highly apprecaited.
Your code is close. just remember that a data grid will persist in a round trip (post back), and MORE important that if you ONLY data bind the grid on the FIRST postback = false?
Then the grid will display but the row data bind event does not re-fire (and thus no total)
So, we assume that on page back we re-bind.
Now you have this code:
total= lbl.Text.ToString();
You need
total = total + lbl.Text.ToString()
Or, of course this:
total += lbl.Text.ToString()
Or more so, you want a final total, then
total += lbl.Text * tbq.Text
but, what you have should work.
Edit:
I now see the problem is that the total price is not updating right away. But we should at least GET the final total working upon page re-fresh.
If you want the total to update as you edit? Then most easy would be in your text changed event to re-calc the total. So say code like this:
So, you can have your existing code first, and THEN add this loop in the same text changed event:
protected void TextBoxE_TextChanged(object sender, EventArgs e)
{
// total the grid
sTotal = 0;
GridViewRow gvr;
foreach (var gvr in GridView1.Rows)
{
TextBox txtV = gvr.FindControl("lblPrice");
if (txtV.Text != "")
sTotal += lblprice.Text;
}
}
So in your text changed, you can (and need to) re-loop the rows after you updated the one row. So the above loop needs to be run. Keep in mind that the row data bound event fires for EACH row on a databind. If you on post back do a gridview databind, then you will of course loose the values in the grid. However, my bets is that you NOT doing a databind, and thus a simple loop to re-total the amount should work just fine.
The MAJOR issue here is that you left out the WHOPPER of a issue. What is that? Why of course you left out where you total things up in the first place. Since that part of yours was wrong (or at least looks to be), then my post FIRST addresed that issue and you need the +=. If your total on intitail load works, then you shoud have posted that code and how it works - since what you posted will not work.
So now that we cleared up why my post addressed the lack of total on first render.
Once you get that working (and you should have posted how that works), then and ONLY then can we address the text changed event. As above shows, it is a easy matter to re-loop and total up all rows since your changes will persist and be in that data - so right after your text changed - run/add/do the above loop to re-total.

ASP.net GridView InvalidOperationException on foreach when deleting

I'm using ASP.net and i've added a delete button on a gridview and im trying to remove the row of the button clicked. The thing is though, that i get an InvalidOperationException on my foreach.
I may have other errors in the code or my logic may be wrong so if you see any of it please point them out. Thanks.
gridView cart.ASPX:
<asp:GridView ID="CartGrid" runat="server" AutoGenerateColumns="false" OnRowDeleting="RemoveSelected">
<Columns>
<asp:BoundField DataField="product_name" HeaderText="Name" />
<asp:BoundField DataField="price_per_unit" HeaderText="Price" />
<asp:BoundField DataField="unit" HeaderText="Unit" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="delSelected" runat="server" Text="Delete" CommandName="Delete"></asp:LinkButton>
</ItemTemplate>
<ItemStyle Width="100px" />
</asp:TemplateField>
</Columns>
</asp:GridView>
delete method cart.ASPX.CS
protected void RemoveBtn(object sender, GridViewDeleteEventArgs e)
{
ArrayList cartList = (ArrayList)Session["cartList"];
GridViewRow row = (GridViewRow)CartGrid.Rows[e.RowIndex];
String name = row.Cells[0].Text;
//String name = (string)CartGrid.DataKeys[e.RowIndex].Value;
//String name = CartGrid.SelectedRow.Cells[1].Text;
foreach (product p in cartList)
{
if (p.product_name.Equals(name))
{
cartList.Remove(p);
}
}
CartGrid.DataBind();
}
Hi I think the issue is that you are using the cartlist for loop and at the same time you want to delete values from the same which is not possible .
just you need to change your approach like create the empty list and add all the index into it from where you have to delete the value Staring from bottom to top like from end of list so that it can not effect the index of the list by deleted value and after loop you can delete it using the new empty list which contain the list of all the values which should be deleted.
You can't modify the collection you're iterating over with the foreach - please see this question for more information.

Bind/Display the two different columns data together inside a Dropdown for a particluar Id in "Edit" mode of RadGrid

I have 4 columns in Telerik RadGrid
1) Account Code (only column shown in "Edit" and "Add" mode - Dropdown)
2) Account Description
3) Amount
4) Remark
Below is the "Add" mode code I am using:
HTML code:
<mastertableview ShowHeadersWhenNoRecords="true" autogeneratecolumns="false" datakeynames="AccountCodeID" InsertItemDisplay="Top"
insertitempageindexaction="ShowItemOnCurrentPage" ShowFooter="True" CommandItemDisplay="Top">
<Columns>
<telerik:GridEditCommandColumn></telerik:GridEditCommandColumn>
<telerik:GridTemplateColumn UniqueName="AccountCode" HeaderText="Account Code">
<ItemTemplate>
<asp:Label ID="lblAcCode" Text='<%# Eval("AccountCode") %>' runat="server"></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlAcCode" DataTextField="AccountDescription" DataValueField="AccountCodeID" runat="server"/>
</EditItemTemplate>
</telerik:GridTemplateColumn>
<telerik:GridBoundColumn DataField="AccountDescription" HeaderText="Description" UniqueName="AccountDescription" SortExpression="AccountDescription" InsertVisiblityMode="AlwaysHidden" ReadOnly="true" ></telerik:GridBoundColumn>
<telerik:GridBoundColumn aggregate="SUM" DataField="Amount" HeaderText="Amount" FooterText="Total : " UniqueName="Amount" SortExpression="Amount"></telerik:GridBoundColumn>
<telerik:GridBoundColumn DataField="Remark" HeaderText="IFCA Remark" UniqueName="Remark" SortExpression="Remark">
</telerik:GridBoundColumn>
<telerik:GridButtonColumn CommandName="Delete" Text="Delete" UniqueName="DeleteColumn"></telerik:GridButtonColumn>
</Columns>
<EditFormSettings>
<EditColumn ButtonType="ImageButton" />
</EditFormSettings>
<CommandItemSettings AddNewRecordText="Add new record" RefreshText="Refresh"></CommandItemSettings>
</mastertableview>
C# code:
protected void RGGSTAcCode_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item is GridEditableItem && e.Item.IsInEditMode)
{
GridEditableItem item = e.Item as GridEditableItem;
string CompanyCode = ddlCompany.SelectedValue.ToString();
DropDownList list = item.FindControl("ddlAcCode") as DropDownList;
list.DataTextField = "AccountDescription";
list.DataValueField = "AccountCodeID";
list.DataSource = GetAccCode(CompanyCode);
list.DataBind();
list.Items.Insert(0, "- Select -");
}
}
protected void RGGSTAcCode_InsertCommand(object sender, GridCommandEventArgs e)
{
GridEditableItem item = e.Item as GridEditableItem;
DropDownList accountCode = item.FindControl("ddlAcCode") as DropDownList;
string SelectedAccCode = accountCode.SelectedItem.Text;
//split dropdown 2 vales
string accCode = SelectedAccCode.Substring(0, SelectedAccCode.IndexOf('-')).Trim(); //getting a/c code
string accDesc = SelectedAccCode.Substring(SelectedAccCode.IndexOf('-') + 1).Trim(); //getting a/c descr
InsertAccountCode(new Guid(TempGUID.Text), accCode, accDesc);
BindGrid();
RGGSTAcCode.Rebind();
}
"Account code" column is only shown in "Add" and "Edit" mode of RadGrid. It is a Dropdown in which I have to bind the 2 values together i.e., Account code + Account Description, and have to show and save it in separate columns of Database. (i.e, Account Code value in Account code column and Account Description value in Description column)
Now my requirement is that: While doing "Edit", I want to bind/display the "Account code" column data and "Account Description" column data together inside Dropdown, which is saved in Database for a particular ID. Just like we bind dropdown while Edit.
and later after Editing the Dropdown item, data will be saved to two different columns of DB as I am doing while Adding the records.
Only I am not getting how to display/bind the two different columns data together inside a Dropdown when doing "Edit".
Please suggest some solution.
I hope I am able to make my requirement clear.
Thanks in advance.
Hmm.. Clear your thoughts about this issue.
What type of databind you are using ? whether advanced databind / sqldatasource databind?
Anyway you have four columns in your grid right! so change your select query like below one.
SELECT accountcode, accountdesc, amount, remark, convert(varchar(20),accountcode)+' '+accountdesc as accdetail FROM YOURTABLENAME
<-- Note down that accdetails.
I'm concatanating the fields accountcode and accountdesc as accdetail (with a empty space ).
So now your grid has 5 rows. Hide the fifth row in the gridview using Visible="false" in that accdetail column.
Don't modify the accountcode column.
Do the change only in Dropdownlist.
<asp:DropDownList ID="ddlAccdetail" DataTextField="accdetail" DataValueField="accdetail" runat="server"/>
Now the dropdown will show the content as accountcode accountdesc in editmode.
On Insert, do the following code change
protected void RGGSTAcCode_InsertCommand(object sender, GridCommandEventArgs e)
{
GridEditableItem item = e.Item as GridEditableItem;
DropDownList ddlAccdetail = item.FindControl("ddlAccdetail") as DropDownList;
string Accdetail = ddlAccdetail.SelectedItem.Text;
string accCode=Accdetail.Split(' ')[0]; //Splitting the string
string accDesc=Accdetail.Split(' ')[1]; //with that added empty space
InsertAccountCode(new Guid(TempGUID.Text), accCode, accDesc);
BindGrid();
RGGSTAcCode.Rebind();
}
Thats it, hope it will work. But keep it in mind if you have any empty space in your accountcode or accountdesc field by default, then you need to change that Empty space to any special character like ( - , * , / ,)

How to hide a column but still access its value?

I have a gridview, with some columns. I want to hide one column, but still access its value when I select a record.
Could someone help me to achieve this?
Any Help is appreciated.
This is my gridview: OutlookID is the column to hide!
<asp:GridView ID="gvOutlookMeldingen" runat="server"
AllowSorting="True" AutoGenerateColumns="False"
AutoGenerateSelectButton="True" onselectedindexchanged="GridView_SelectedIndexChanged">
<Columns>
<asp:BoundField DataField="Melder" HeaderText="Melder" />
<asp:BoundField DataField="Onderwerp" HeaderText="Onderwerp" />
<asp:TemplateField HeaderText="Omschrijving">
<ItemTemplate>
<div style="overflow:auto; width: 500px; height: 150px;">
<asp:Label ID="lblOmschrijving" runat="server" Text='<%# Bind("Omschrijving")%>'></asp:Label>
</div>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Meldingsdatum" HeaderText="Meldingsdatum" />
<asp:BoundField DataField="OutlookID" HeaderText="OutlookID" Visible="false" />
</Columns>
</asp:GridView>
This is the code when I select a record:
Label lblOmschrijving = (Label)gvOutlookMeldingen.SelectedRow.FindControl("lblOmschrijving");
//Label lblOutlookID = (Label)gvOutlookMeldingen.SelectedRow.FindControl("lblOutlookID");
Response.Redirect("Detailscherm.aspx?"
+ "melder=" + Server.UrlEncode(gvOutlookMeldingen.SelectedRow.Cells[1].Text)
+ "&meldingsdatum=" + gvOutlookMeldingen.SelectedRow.Cells[4].Text
+ "&onderwerp=" + Server.UrlEncode(gvOutlookMeldingen.SelectedRow.Cells[2].Text)
+ "&outlookid=" + Server.UrlEncode(gvOutlookMeldingen.SelectedRow.Cells[5].Text)
+ "&omschrijving=" + Server.UrlEncode(lblOmschrijving.Text)
+ "&niv1=" + ""
+ "&niv2=" + "");
Set this code after you've binded the data. To get this functionality I do this:
MyGridView.Columns[0].visible = true;
MyGridView.DataBind();
MyGridView.Columns[0].visible = false;
With this the first column is hidden, but you should be able to acces it's value.
If you don't want the data to be available on the client side, you'll have to set the server-side Visible = "False" property of whatever DataControlField you're using (preferably in the markup). You'll still be able to access the column from the server side.
You might want to consider using the GridView's DataKeys property - it might be more suited to your needs.
Create Template column instead of your SELECT button. Set
PostbackUrl='<%#
Eval("somepage.aspx?id={0}","wanted
column") %>'
. Remove column via designer.
You can also set it invisible at the client side. With Javascript.
document.getElementById(myObject).visible = "false";
when we set visiblity of control false in Design time that will be not render .Try to
set visiblity =false in gridView rowCreated Event .in below code i am setting
second column visibility= false
protected void grid_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Cells[2].Visible = false;
}
if (e.Row.RowType == DataControlRowType.Header)
{
e.Row.Cells[2].Visible = false;
}
if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Cells[2].Visible = false;
}
}
and now try to Get Value .Surely you will get the value.
I had the same issue.
You can't hide the column and keep value in code behind.
You have to hide it directly on client side with a javascript.
I did that :
On my css or page :
<style type="text/css">
.hiddencol
{
display: none;
}
.viscol
{
display: block;
}
</style>
Then add style into the BoundField of the gridViewer.
For example :
<asp:BoundField DataField="AgentGUID" HeaderText="AgentGUID" ReadOnly="True" SortExpression="AgentGUID"
meta:resourcekey="BoundFieldResource1">
<HeaderStyle CssClass="hiddencol" />
<ItemStyle CssClass="hiddencol" />
<FooterStyle CssClass="hiddencol" />
</asp:BoundField>

How do I edit data being bound to a datagrid?

In reference to Link loaded into my gridview try to navigate to my local server. The columns I have in the datagrid are Customer #, Description, Link.
I've got a function set up that's called on rowDataBound, but how do I retrieve what link is in the row so that I can edit it, and then rebind it to the datagrid?
protected void grdLinks_RowDataBound( object sender, GridViewRowEventArgs e )
{
if ( e.Row.RowIndex == 2 )
{
}
}
And here is my gridview code
<asp:GridView ID="grdLinks" runat="server" AutoGenerateColumns="False" DataSourceID="ldsCustomerLinks"
OnRowDataBound="grdLinks_RowDataBound" EmptyDataText="No data was returned."
DataKeyNames="ID" OnRowDeleted="grdLinks_RowDeleted" Width="80%" BackColor="White"
HorizontalAlign="Center" BorderColor="#999999" BorderStyle="None" BorderWidth="1px"
CellPadding="3" GridLines="Vertical">
<RowStyle BackColor="#EEEEEE" ForeColor="Black" />
<Columns>
<asp:BoundField DataField="CustomerNumber" HeaderText="Customer Number" SortExpression="CustomerNumber" />
<asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
<asp:HyperLinkField DataTextField="Link" HeaderText="Link" SortExpression="Link" DataNavigateUrlFields="Link" Target="_blank" />
</Columns>
</asp:GridView>
<asp:LinqDataSource ID="ldsCustomerLinks" runat="server" ContextTypeName="ComplianceDataContext"
TableName="CustomerLinks" EnableDelete="true">
</asp:LinqDataSource>
If I'm understanding you correctly, you want to get the value of a data item called Link. If so, then something like this should work:
EDIT: I think what you're saying is that you want to grab the value Link from the database, manipulate it and then set the Url of the HyperLink to the new, manipulated value, if so then it would look like this:
ASPX Page (Updated to reflect posted code)
<Columns>
<asp:BoundField DataField="CustomerNumber" HeaderText="Customer Number" SortExpression="CustomerNumber" />
<asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
<asp:TemplateField HeaderText="Link">
<ItemTemplate>
<asp:HyperLink ID="hlParent" runat="server" Text='<% #(Eval("Link")) %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
I modified the ASP from your original question by adding an ID and removing the reference to the NavigateUrl attribute from the HyperLink control.
Code
protected void grdLinks_RowDataBound( object sender, GridViewRowEventArgs e )
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string link = DataBinder.Eval(e.Row.DataItem, "Link") as string;
if (link != null && link.Length > 0)
{
// "FindControl" borrowed directly from DOK
HyperLink hlParent = (HyperLink)e.Row.FindControl("hlParent");
if (hlParent != null)
{
// Do some manipulation of the link value
string newLink = "https://" + link
// Set the Url of the HyperLink
hlParent.NavigateUrl = newLink;
}
}
}
}
RowDataBound is called for every row in the GridView, including headers, footers, etc. Therefore, you should start by examining only the rows containing data.
Once you're on a row, there are several ways to examine the cells. One is just to use the cell index (2 here). That seems simple in your situation, but will lead to frustration if you ever rearrange the columns.
Here's an example of that from MSDN:
void CustomersGridView_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>";
}
A better way is to use FindControl with the item's ID.
protected void gvBarcode_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
HyperLink hlParent = (HyperLink)e.Row.FindControl("hlParent");
}
}
You may also want to look into letting the gridview do it for you.
You can use the datanavigateurlformatstring property to insert querystring parameters if that's what you are trying to do.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.hyperlinkfield.datanavigateurlformatstring.aspx

Categories