gridview column boundfield error - asp.net

Inside GridView, then inside columns I have a bound field
<asp:BoundField DataField="Company Name" HeaderText="Company Name" SortExpression="Name" />
This displays a list of columns of the companys name (which is fine) however the headerText, is a clickable link that throws an error...how can i get the headertext just to display as a normal plan unclickable label
ta

You can use AllowSorting="False" to the gridview.
<asp:GridView AllowSorting="False">
<asp:BoundField DataField="Company Name" HeaderText="Company Name"/>
</asp:GridView>

Probably because you marked the bound field to be sortable and you didn't implement the sort on the server side... probably. Remove the SortExpression and see what's happening. You should post more info starting with the exception you have.

just remove the SortExpression

Related

Dynamically created Labels and TextBoxes are unable to be positioned

I am building a dynamically created popup window that contains a dynamically created grid and controls (Labels and TextBoxes).
The grid part is working correctly, and not an issue. However, the controls are giving me issues.
The idea is to create a Label and a TextBox for each of the columns in the Grid. I am able to create them fine, but am unable to position them at all. label.Location, label.Top, label.point, etc. return an error saying that it is not part of Label. The same thing happens with the TextBox.
When they do display, they appear in a horizontal row with the TextBox overlapping the Label unless the width is set sufficiently large enough (which of course leave a bunch of empty space).
I would like the to be vertically aligned with the TextBox immediately after the Label.
Something like:
labelText: TextBox
These controls are being added into an asp:Panel (pnlFields)
For Each col As DataColumn In dataTable.Columns
Dim label As New Label()
label.Text = col.ColumnName & ": "
label.Height = 24
label.Width = label.Text.Length()
pnlFields.Controls.Add(label)
Dim textBox As New TextBox()
textBox.Height = 24
textBox.Width = 100
pnlFields.Controls.Add(textBox)
Next
I would like to try to have the Label width be as long as the text it contains instead of static, that way I would (hopefully) be able to set the TextBox location to be right after the Label.
In any event, I can't seem to specify a position at all in order to do this.
Any ideas?
Thanks!
Edit: Markup
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<asp:Panel runat="server" ID="pnlFields" CssClass="FormStyle" Height="600px" />
<asp:Panel runat="server" ID="pnlFinder" CssClass="FormStyle">
<telerik:RadGrid ID="batchRecords" runat="server" Skin="Windows7" ShowHeader="true" AutoGenerateColumns="true" Width="600px" AutoPostBack="true">
<MasterTableView CommandItemDisplay="Bottom" AllowPaging="true">
<CommandItemSettings ShowAddNewRecordButton="false" />
<Columns>
<telerik:GridButtonColumn UniqueName="selectRecord" HeaderText="Edit" CommandName="Select" Text="Edit Record" ButtonType="ImageButton" ImageUrl="~/images/icons/pencil.png">
</telerik:GridButtonColumn>
</Columns>
</MasterTableView>
</telerik:RadGrid>
</asp:Panel>
</asp:Content>
I really, but really don't see the need for creating those text boxes. there is a LARGE number of built in repeating controls. If you create those controls on the fly, then you can NOT wire up the code behind events - so you quite much give up the WHOLE reason for using asp.net and ALL of those great built in controls.
I see no reason why you can inject and include some extra "divs" and apply style to those divs. But, before you go down that road?
You should attempt to make a VERY STRONG case as to why you going down this road as opposed to using a listview, gridview, or a repeater control. They are designed for repeating data over and over - and do so WITH VERY LITTLE code and VERY LITTLE markup.
and where does the data come from that going to fill out these controls? Or even the reverse - where is the reulsts of the controls going to be placed? You see, by using say a repeater or whatever? They are data bound. So, a person can say add 2 or 15 rows of data, and then in ONE sql update operations you can write out ALL of that data! - in other words, you are repeating some controls - but based on what and how is the big question here?
And as noted, if you create + inject such controls, then you can't have nor wire up events for these controls. So, think very long and hard as to the final goal here. You might fix the layout issues, but then your next issue/problem will be event code, and then after that, will be the complex code required to take that input and somehow push it back out to some database. As a result, I really don't recommend this road.
Further more, using one of those built in "repeating" objects allows you with relative ease to enable editing of that data on screen, and as noted, writing back one row, or 15 rows of data can be done with the same code - and with far greater ease then trying to inject dynamic controls into that form. Furthermore, what "id" are you going to use for referencing those controls and once you managed to inject these controls?
The end goal here is the key concept.
I find that gridview is nice - often less mark up. However WHEN you start to have say 3 or more custom controls in that grid? Then I like listview over that of gridview (because listview allows you to drap + drop and use standard asp.net controls WITHOUT having to put that control inside of a template block. But, your case? Only two extra controls for each row of the grid? then sure, stick with grid view.
So, to add those two extra columns to that grid? You can do this:
First, I will use the wizard to create this gridview. I THEN blow out the data sourceID setting and also chop out the datasource control on the form.
So, I count less then 1 minute - drop gridview. Click on the configure data source from the form. This one:
So I configure the data source, generate the gv, AND THEN remove the data source ID and also remove the data source control from the markup. So, it takes 30 seconds of time, and I wind up with this grid:
So, we get this:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
</Columns>
</asp:GridView>
And the code to load this grid up is this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Using cmdSQL As New SqlCommand("SELECT ID, FirstName, LastName, HotelName, City from tblHotels",
New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
GridView1.DataSource = cmdSQL.ExecuteReader
GridView1.DataBind()
End Using
End Sub
And now we have this:
Ok, not bad for less time then it took me to WRITE this post!!!
And note how we only up to about what - 3 lines of code to load up the grid?
Super easy.
Ok, so now lets add a label, and a text box to the grid.
Well, just do this for the gv template:
So, note how we just added two extra columns. The markup is like this:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
<asp:TemplateField HeaderText = "My label">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText = "My Text Box">
<ItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Now, when we run the above, we get this:
I mean was that easy or what? And I could have placed that lable + text box in the SAME TEMPLATE column. So you quite much free to add those extra columns to that grid, and we did not have to write code - and in fact it was VERY easy, and the result is we now have that extra two columns - and achieve this WITH GREAT ease.
And we can also with relative ease set/change the values of the label and text box - even based on other colum data from that row, and can do that again with great ease.
So, at the end of the day? I don't suggest you try and manual add two columns when we have such a great approach as outlined above. and even better, is the values the user types into each row and text box can via code be pulled and refreenced from that gv - and done so with great ease for 2 rows, or 20 rows of data.
Edit:
Since the controls and addtions to the gv are to be at run time (dynamic), then you STILL WANT to use the gv object model - fighting against that model is a REALLY bad idea - go with the flow.
So, you can add extra bound field columns to the gv this way:
Sub LoadGrid()
Using cmdSQL As New SqlCommand("SELECT ID, FirstName, LastName, HotelName, City from tblHotels",
New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
GridView1.DataSource = cmdSQL.ExecuteReader
AddColumns()
GridView1.DataBind()
End Using
End Sub
Sub AddColumns()
Dim lblfield As New BoundField()
lblfield.HeaderText = "Label1"
GridView1.Columns.Add(lblfield)
Dim txtfield As New BoundField()
txtfield.HeaderText = "TextBox"
GridView1.Columns.Add(txtfield)
End Sub
And then on item bound event, you can also then inject the controls of your choosing like this:
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim MyLabel As New Label
MyLabel.ID = "Label1"
MyLabel.Text = "Label Text"
e.Row.Cells(5).Controls.Add(MyLabel)
Dim MyTextBox As New TextBox
MyTextBox.ID = "Textbox1"
MyTextBox.Text = "Text box value"
e.Row.Cells(6).Controls.Add(MyTextBox)
End If
End Sub
so, now with this simple markup:
<link href="Content/cuscosky.css" rel="stylesheet" />
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
</Columns>
</asp:GridView>
So, with above code? We get the SAME results, and this output:
Edit:
I solved this by creating an HTML Table in the markup, then programmatically adding Rows and Cells with controls (Labels and TextBoxes) and unique IDs. I was then able to find and populate those controls with the correct data.
Worked MUCH easier than trying to manually position each control.
I was able to solve the issue of positioning the controls.
I needed to use label.Style.Add() and put in the values needeed.
It seems to be working correctly now.
Thanks!

How to use Session to save value on current row of GridView, to be copied into TextBox? - VB.Net

I'm trying to use Session to record the data of the 1st column of current row to be used in another Web From which will be opened using a LinkButton that is in the GridView.
Basically, if I click the LinkButton on the 1st row, the 1st column data of the 1st row will be copied to the next Web Form. But before I do that, I want to do a smaller scale experiment to test it. So instead for now I want the Session to copy the data into a TextBox in the same form.
For reference, here is the design of the GridView, most rows removed since they're not relevant:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
BorderColor="Black" BorderStyle="Solid" BorderWidth="1px" Font-Names="Arial">
<AlternatingRowStyle BackColor="#B7DBFF" />
<Columns>
<asp:BoundField DataField="caseticket" HeaderText="Ticket #" >
<HeaderStyle BackColor="#000066" ForeColor="White" Wrap="False" width="10%"/>
<ItemStyle Wrap="False" />
</asp:BoundField>
<asp:TemplateField ShowHeader="False">
<HeaderStyle BackColor="#000066" ForeColor="White" Wrap="False" width="10%"/>
<ItemTemplate>
<asp:linkbutton ID="newLog" runat="server" onclick = "CaseLog_click" >Add Log </asp:linkbutton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle BackColor="#000066" />
<RowStyle HorizontalAlign="Center" />
</asp:GridView>
For the TemplateField is a LinkButton with a onclick property. With it, I created the sub:
Sub CaseLog_click(ByVal sender As Object, ByVal e As EventArgs)
Session("ticket") = GridView1.SelectedRow.Cells(1).Text
'Response.Redirect("~/CaseLog.aspx") ==> will be using this to proceed to next Web Form
TextBox1.Text = Session("ticket") '==> For test use only.
End Sub
If I only kept the Response.Redirect("~/CaseLog.aspx") in the sub, the LinkButton can direct me to the next Web Form. But as it is now, during testing when I use the LinkButton I get an error on the session line of the sub.
Object reference not set to an instance of an object.
Is the code salvageable, or do I need to redo this?
Thanks.
It looks like the button event to select the row is not wired up.
I would use say this:
<asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
<asp:ButtonField CommandName="Select" HeaderText="Select" ShowHeader="True" Text="Button" />
Note CAREFULL how we put the CommandName="Select" in above. If you don't do this, then the selected row does not come though correctly to the click event you have.
You could try the select command as per above on your link button, but I would just use the above. Now, hightlight the grid in the form desinger. On the properity sheet, go to events, and double click on the SelectedIndex Change event. So, your buttion is not changing the selected index correctly.
The code stub will look like this:
Protected Sub GridView1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles GridView1.SelectedIndexChanged
Dim lgridrow As GridViewRow = Me.GridView1.SelectedRow
Debug.Print("<" & lgridrow.Cells(0).Text & ">")
Debug.Print("<" & lgridrow.Cells(3).Text & ">")
Debug.Print("<" & Me.GridView1.SelectedRow.Cells(3).Text & ">")
End Sub
Note VERY careful how the event code stub is setup - the event args are different then yours.
So, you can try the CommandName="Select" in your existing code, but if not, then try the above button field as opposed to your custom asp.net button you have. As it stands, it don't look like your asp.net button is firing the row-changed event.
Edit and follow up:
Can I have extra buttons - run their own code?
Yes, you can. You can do this several ways (one is to pick up which button was clicked in the SelectedIndex change event.
Or, you can drop in extra buttons and use that event code stub.
So, in my example, lets add an extra button.
we now have this:
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
<asp:ButtonField CommandName="Select" HeaderText="Select" ShowHeader="True" Text="Button" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click"
CommandName="MySelect" CommandArgument ="<%# Container.DisplayIndex %>"
style="background-color:gray;color:white;text-decoration:none;padding-left:6px;padding-right:6px"
text="Mybutton"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
We thus have this:
Now, we can attach/have button code for the extra button. But NOTE careful we did NOT use the built in SELECT for the command argument. The REASON is that if we have Command=select, then the selected index WILL fire, but AFTER our button code stub. That means we cannot use the selectedrow (too early).
So, what we do/did in above was have the CommandArguemnt PASS the selected row value - that value will pass ok, and thus we don't care that the selected index event does not fire (and by CHANGING our command argument to NOT "select", then in fact the selectedindexchange event DOES NOT fire.
As a result, we use the passed row in the command argument, and we have this for the button code:
Protected Sub LinkButton1_Click(sender As Object, e As EventArgs)
Dim ixrow As Integer = sender.CommandArgument
Debug.Print(Me.GridView1.Rows(ixrow).Cells(0).Text)
End Sub
And note while we are editing the markup, intel-sense will give a list of options when editing. Eg this:
So, that gives us a chance to wire up (add) a standard click event). No selected index code stub is required (since the button would fire before selected index anyway). So we are now manually wiring up this event. We are NOT thus using the selectedindex change event - we don't even need it.
So, now in our button stub, we are free to do anything we want - including jumping to another page
eg:
Protected Sub LinkButton1_Click(sender As Object, e As EventArgs)
Dim ixrow As Integer = sender.CommandArgument
Debug.Print(Me.GridView1.Rows(ixrow).Cells(0).Text)
Session("HotelName") = Me.GridView1.Rows(ixrow).Cells(3)
Response.Redirect("~/ShowHotelDetails.aspx")
End Sub
So, to add separate code buttons:
Don't use selected index change event - you MIGHT still want it to run but it will run/fire AFTER your button code (so can't use selectedrow - too early).
But, you do need Command="myjunk" because without a command, then the command argument does not work. By passing the row index in commandargument, then we are free to grab data from the gridview as per above code via row index.
So, you can well dump the selected index change event. You just have to pass the row index, and work from that. The code stub can thus walk the dog, setup values in session, or even pass/make the url with parameters.

how to retrieve checkbox values in gridview?

I have a grid-view on which each row consists check box, and there is a button outside the grid-view. when i check some rows on grid-view and clicking those button, i need to insert the checked rows details into another table of database. I have created the grid-view like this
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="student_name" HeaderText="student_name" SortExpression="student_name" />
<asp:BoundField DataField="student_id" HeaderText="student_id" SortExpression="student_id" ReadOnly="True" />
<asp:BoundField DataField="student_nric" HeaderText="student_nric" SortExpression="student_nric" />
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox AutoPostBack="false" Id="CheckBoxUpdate" runat="server" />
</ItemTemplate></asp:TemplateField>
</Columns>
</asp:GridView>
but dont know how to store the checked rows value to datatable. please help
On button click on which you want to save the values in the database.
Loop through earch row of the gridview.
Find the checkbox in that row
Check if it is checked or not
foreach (GridViewRow row in GridView1.Rows)
{
if (((CheckBox)row.FindControl("CheckBoxUpdate")).Checked)
{
//insert here
}
}
Here is a good link for the same
http://www.c-sharpcorner.com/Forums/Thread/201835/loop-through-gridview.aspx
You can use a stringbuilder object to iterate through the rows of the checkbox and store the value. see this tutorial
http://www.codeproject.com/Articles/11207/Selecting-multiple-checkboxes-inside-a-GridView-co

Redirect to specific page when a gridview buttonfield is clicked

I have two fields in my gridview. One is a field with a date range and one of them is a buttonfield. I want to make it so that when a button is clicked, it will redirect them to a specific page with a formatted string similar to how it's done when a hyperlinkfield is clicked as such:
DataNavigateUrlFormatString="ProductInfo.aspx?ProductID={0}"
However, I don't want to use the other field's value(the date range). I want to use the primary key of the record which is "SundayOfWeek". The user wants a button rather than a hyperlink. Is there a way I can do the same thing with a button?
Try using this type of column instead of a ButtonField:
<Columns>
<asp:HyperLinkField
DataTextField="ProductName"
HeaderText="Product Name"
SortExpression="ProductName"
DataNavigateUrlFields="ProductID"
DataNavigateUrlFormatString="ProductInfo.aspx?ProductID={0}" />
</Columns>
Sure, one of many ways is this:
<columns>
<asp:templatefield headertext="Button">
<itemtemplate>
<asp:Button id="btnRedirect"
Text= "Click me"
CommandArgument='<%#Eval("SundayOfWeek")%>'
OnClick="DoRedirect"
runat="server"/>
</itemtemplate>
</asp:templatefield>
</columns>
protected void DoRedirect(object sender, EventArgs e)
{
Button theButton = sender as Button;
Response.Redirect("Newpage.aspx?ID="+theButton.CommandArgument);
}
If you don't want to use the date-range field, you should use another column as DataNavigateUrlField:
DataNavigateUrlField="KeyField"
DataTextField="DateField"
DataNavigateUrlFormatString="ProductInfo.aspx?ProductID={0}"
If you don't want to use a HyperLinkColumn, you should use a TemplateField and add a Button:
<asp:TemplateColumn>
<input type="button" onclick="location.href='ProductInfo.aspx?ProductID=<%#Eval("KeyField")%>'" value='<%#Eval("DateField")%>'' />
</asp:TemplateColumn>

Binding GridView to array of strings. Problem with HyperLinkField

I know that you can use exclamation sign to bind array of simple types (like string) to GridView like this
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:BoundField HeaderText="Array Field" DataField="!" />
</Columns>
</asp:GridView>
But this doesn't seem to be the case with DataNavigateUrlFields
<asp:HyperLinkField DataNavigateUrlFields="!" DataNavigateUrlFormatString="RoleInformation.aspx?role={0}" Text="Manage users" />
and I get following error:
A field or property with the name '!' was not found on the selected data source.
Most people probably haven't even know to use the ! field I suspect. When I read your question it actually made me remember that feature which I had read about but never actually used. With that in mind, I don't think there is a way with that type of field because it was probably forgotten in the HyperLinkField implementation (just a guess). You could just do a quick conversion to named property and then you don't have any issues:
Example:
<asp:GridView ID="grdTest" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:BoundField HeaderText="Array Field" DataField="data" />
<asp:HyperLinkField DataNavigateUrlFields="data" DataNavigateUrlFormatString="RoleInformation.aspx?role={0}" Text="Manage users" />
</Columns>
</asp:GridView>
Notice the field named data. Then to bind your array just do:
string[] testArray = { "1", "2", "3" };
grdTest.DataSource = testArray.Select(a => new { data = a });
grdTest.DataBind();
It doesn't replace the ! directly but it is a simple solution to get around binding to simple arrays that will always work even when the ! isn't implemented which it probably needs to be for each field type.

Resources