How do you call a codebehind/class method from a gridview in an aspx page? Also, I need to pass the value of databound column to that method. Is this possible?
Something like this:
<asp:BoundField DataField="Precision" />
<asp:BoundField DataField="MyNumber" DataFormatString="FormatHelper.Format(MyNumber, Precision)" />
Edit: I tested this to work.
<asp:TemplateField HeaderText="My Number">
<ItemTemplate>
<asp:Label runat="server"
Text='<%# Eval("MyNumber", FormatHelper.Format((decimal)Eval("MyNumber"), (decimal)Eval("Precision") )) %>' />
</ItemTemplate>
</asp:TemplateField>
This works because the Eval method takes the DataFormatString as an optional second parameter. note: Make sure you replace the casts with the appropriate types for the method signature.
An easier way might be to bind to a linq-to-objects projection instead.
myGridView.DataBind( from foo in fooList
select new {
MyNumber = MyNumber,
Precision = Precision,
MyFormattedNumber = FormatHelper.Format(MyNumber, Precision),
} );
GridView.DataKeys Property
Button.CommandArgument Property
Create a template field in the gridview.
Add a button to the template field and give the button a
commandName (example: "btn")
Handle the rowdatabound event and check if rowType=DataRow then:
Get the button within this row using the FindControl method then
fill in its CommandArgument the value you want(example: e.Row.DataItem("ID"))
Handle the rowcommand event:
if commandname="btn" then
the button is clicked
Related
I have been trying to write this simple logic of deleting a row from the gridview and from the SQL database of the selected row, but keep getting a null reference to cell, which has the primary key [ID] in a field.
Here's my html:
<asp:GridView ID="grvInventoryEdit" runat="server" BackColor="White" onrowdeleting="grvInventoryEdit_RowDeleting"
onrowediting="grvInventoryEdit_RowEditing"
onrowupdating="grvInventoryEdit_RowUpdating">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:CommandField ShowDeleteButton="True" /><asp:TemplateField HeaderText="Id">
<ItemTemplate>
<%#Eval("No")%>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="txtEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>........ </Columns> </asp:GridView>
And my back-end code for rowdeleting event is :
protected void grvInventoryEdit_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
TextBox id = (TextBox)grvInventoryEdit.Rows[e.RowIndex].FindControl("txtEditNo");
Asset asset = db.Assets.Single(a => a.No == Convert.ToInt32(id));
db.Assets.DeleteOnSubmit(asset);
db.SubmitChanges();
binddata();
}
and when the event fires, this is what i am seeing while debugging:
I am not sure why i am getting a null value ,though, there is a value for that cell.
Could you tell me what i am doing wrong ?
Regards,
Might be it is due to the readonly property of textbox, not suer.
If you want to use the image button for edit and delete then use
protected void ibtnDelete_Click(object sender, ImageClickEventArgs e)
{
GridViewRow gvRow = (GridViewRow)((ImageButton)sender).NamingContainer;
Int32 UserId = Convert.ToInt32(gvUsers.DataKeys[gvRow.RowIndex].Value);
// delete and hide the row from grid view
if (DeleteUserByID(UserId))
gvRow.Visible = false;
}
For complete code see
You are passing TextBox object instead instead of Text property of TextBox
Asset asset = db.Assets.Single(x=>x.No == Convert.ToInt32(id.Text));
and your TextBox is also coming null means it's unable to find it in GridView, try like this:
TextBox id = e.Row.FindControl("txtEditNo");
Also see this CodeProject article to understand how to use ItemTemplate and EditItemTemplate
why are you adding a second commandfield instead of just enabling the delete button on the existing one.
if you are using a command field you should be supplying an compatible datasource that provides Delete functionality
if you're "rolling your own" delete functionality then just use a regular Button control and supply a CommandName and CommandArgument, such as CommandName="MyDelete" CommandArgument=<row number> where <row number> is supplied via GridView RowDataBound() event.
Regardless of how you choose to implement Delete you should be placing the key field in the GridView DataKeys Property and not as a field within each row. This will make obtaining the PK far easier than what you are trying to do
I guess, in my HTML, i have only the value that's bound to the item, is being displayed, and there are no textboxes in my <ItemTemplate>, hence, it pulls null value. Whereas, in my <EditItemTemplate> there is a textbox, which can pull the value from the cell.
So I changed my HTML to this:
<asp:TemplateField HeaderText="Id">
<ItemTemplate>`<asp:label runat="server" ID="lblEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="txtEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
and no change in my codebehind, and this resolved the issue.
I have a ListView nested inside the column of a GridView, which looks something like this:
<asp:panel id="myPanel" Runat="server" EnableViewState="False">
<asp:GridView id="myDescription" AutoGenerateColumns="False" Width="100%" runat="server"
OnRowCommand="my_RowCommand" OnRowDataBound="GetDataForListView" EnableViewState="False">
<Columns>
<asp:BoundField DataField="id" HeaderText="ID">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:BoundField>
<asp:BoundField DataField="data1" HeaderText="Thing 1">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:BoundField>
<asp:BoundField DataField="data2" HeaderText="Thing2">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:BoundField>
<asp:BoundField DataField="data3" HeaderText="Thing3">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:BoundField>
<asp:TemplateField SortExpression="id">
<ItemTemplate>
<asp:HyperLink id="hlView" runat="server" NavigateUrl="...">View</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Column to contain my list of things">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
<ItemStyle HorizontalAlign="Center"></ItemStyle>
<ItemTemplate>
<% /* This is my list view: */ %>
<asp:ListView ID="myListView" runat="server" OnItemCommand="DoSomething" EnableViewState="False">
<ItemTemplate>
<asp:LinkButton ID="lbAttachment" Runat="Server" Text='<%# Eval("FILE_NAME") %>'
CommandName='<%# Eval("ROW_NUM") %>' CausesValidation="False" >
</asp:LinkButton><br/>
</ItemTemplate>
</asp:ListView>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</asp:panel>
The data is successfully binding, but the OnCommand event is not being fired on clicking the LinkButton (nor is any other event for the LinkButton, such as an OnClick event).
The rendered HTML for the link button shows that on clicking it, the page is performing a postback: javascript:__doPostBack('...','')
This means it is going back into my 'Page_Load' and refreshing the contents of the page - the grid view is binded here.
I can stop it from performing a postback by adding this attribute to the LinkButton:
OnClientClick="return false;"
But this only stops the postback from occurring, the OnCommand event still doesn't fire.
Any ideas?
The event signature in the code-behind is:
protected void DoSomething(object sender, CommandEventArgs e) { ... }
I have also tried using an OnItemCommand event on the ListView control with this event signature, but similarly the event is not invoked:
protected void DoSomething(object sender, ListViewCommandEventArgs e)
The OnRowdataBound event on the parent GridView is successfully invoked, it's only the nested ListView that fails to invoke its event.
The code I have shown is for the 2nd GridView on the page, there is another one too, and it is this one which gets binded on the Page_Load event. The Page Load event has a sequence of events as follows, where the 1st GridView (which we'll call GridView1) is bound:
Page_Load
Data for GridView is retrieved from database
Data is assigned to a 'DataView' object and assigned to the GridView1 DataSource property.
GridView1.DataBind() is invoked
Miscellaneous conditional logic which removes certain columns from GridView1
An OnClick attribute is added to each row.
So actually, the Page_Load binds the first GridView. The 2nd GridView is the one which contains the ListView which I am having a problem with. This 2nd GridView (the code of which is at the top of the post) is populated on the 'OnRowCommand' event of the 1st GridView, and has a sequence like this:
GetDataForListView
Get data from database
Assign the DataSet containing the data to the DataSource property of the 2nd GridView
Call the DataBind() method
Then, as you can see from the code I posted at the top, I have the OnRowDataBound event which fails to invoke its event in the code-behind.
Ciaran, I replicated the whole scenario and found out the below issue.
Issue: When any event related to either the GridView2 or ListView or the LinkButton is being fired it first hits the Page_load function. In the Page_load function you are not data binding GridView2 and the ListView so apparently they almost vanish and so the Event will not be fired.
Possible Fix:
You need to bind the GridView2 in the Page_load function in order fire those related events and the same goes with the ListView Too.
This fix is a very big one. I am not sure if you could try this.
a. If you are binding the GridView2 depending on the condition generated by the GridView1 click then store those parameters in some hidden field.
b. Have a function named LoadGridView2(parameters) where you bind the GridView2 and the ListView depending on the parameters passed and call this function in the Page_Load function each every time a PostBack is done and pass the stored parameters in the hidden field to the LoadGridView2(parameters)
c. By doing above you can bind the GridView2 according the GirdView1 Click condition and make the GridView2 and ListView available in the PostBack too. So now the event could be fired.
Let me know in case of any queries.
LinkButton has OnCommand, ListVIew has OnItemCommand. So the name isn't correct. OnCommand only fires if the LinkButton has a CommandName set. And also, the repeater may swallow the button's command argument. Certain controls do that because of the way events bubble up to the UI.
<asp:LinkButton ID="linkButton" Runat="Server" OnCommand="DoSomething"
CommandName="DoSomething"
CommandArgument='<%# Eval("ROW_NUM") %>' Text='<%# Eval("FILE_NAME") %>'>
</asp:LinkButton>
Or Try adding:
<asp:ListView .. OnItemCommand=".." />
And then do:
void DoSomething(Object Sender, ListViewCommandEventArgs e) {
// Do something
}
Your button would still need to set a command name like:
<asp:LinkButton .. CommandName="DoSomething" />
I have a Gridview which is autogenerated by fetching data from various tables.
Now my requirement is i need to make my first column as hyperlink so that if it is clicked then it has to navigate to another page with hyperlinked value.
In the second page i have Lable this label should show the hyperlink value and based on that the data will be populated on the second page.
For example:
I have a gridview with 10 columns..My first column is Emp Id.
If that id is clicked it has to take me to second page and the label control must get this id value and based on that id the rest of the info like emp name emp DOB should be filled.
i am using C# as my code behind.
Can anyone help me to proceed..
Awaiting ur reply
You need the <asp:HyperLinkField />
<asp:GridView>
<Columns>
<asp:HyperLinkField HeaderText="Id" DataTextField="YourID" DataNavigateUrlFields="YourID"
DataNavigateUrlFormatString="SecondPage.aspx?Id={0}" />
</Columns>
</asp:GridView>
You might need to remove the AutoGenerateColumns="true" property and type the fields yourself, selecting only the columns you want to show - using <asp:BoundFied DataField="ColumnName" />
In case you want to pass multiple values in the querystring, separate the fields with comma
DataNavigateUrlFields="YourID, SecondField"
and your format string would be
DataNavigateUrlFormatString="SecondPage.aspx?Id={0}¶m2={1}"
Other links
HyperLinkField.DataNavigateUrlFormatString Property
How to pass multiple values in HyperlinkField
You can use a TemplateField column in your GridView:
<asp:TemplateField>
<ItemTemplate>
<asp:HyperLink ID="linkToDetails" runat="server" NavigateUrl='Details.aspx?empId=<%# Eval("empId") %>' Text='<%# Eval("empId") %>'></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
On the Details.aspx page you should get the empId from the QueryString and get the details from the database.
This is kind of silly but I have a DetailsView that binds to a record in my database using a sqlDataSource. My problem is that the field I'm binding to is a bit field, (i,e 1 or 0) that at present allows nulls. I realize this needs to change but I also need to be able to handle DBNulls on the GUI side so that the application automatically knows to set the Checked property of the checkbox to "false" if the value is DBNull. At present my template field looks like this.
</asp:TemplateField>
<asp:TemplateField HeaderText="Car:" HeaderStyle-Width="15%" ItemStyle-Width="85%">
<ItemTemplate>
<asp:Label ID="lblIsCar" runat="server" Text='<%# Eval("isCar") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:CheckBox ID="ckIsCar" runat="server" Checked='<%# Convert.ToBoolean(Eval("isCar"))%>' />
</EditItemTemplate>
</asp:TemplateField>
Everything works fine in View mode but when I click the Edit link on the details view control I get the following error:
Object cannot be cast from DBNull to other types.
Any suggestions?
Update:
I need to use 2 way binding through Bind() instead of Eval() as the details view performs an update to the selected record. If i use Convert.ToBoolean() with Bind an exception will be cast. I may end up using a CheckboxField. One would think that there would be an easy way to handle this but I have been unlucky inf finding one.
You could try a conditional to check for DBNull.Value:
Eval("isCar") == DBNull.Value ? false : Convert.ToBoolean(Eval("isCar"))
I have a GridView that is populated via a database, inside the GridView tags I have:
<Columns>
<asp:TemplateField>
<ItemTemplate><asp:Panel ID="bar" runat="server" /></ItemTemplate>
</TemplateField>
</Columns>
Now, I want to be able to (in the code) apply a width attribute to the "bar" panel for each row that is generated. How would I go about targeting those rows? The width attribute would be unique to each row depending on a value in the database for that row.
<asp:Panel ID="bar" runat="server" Width='<%# Eval("Width") %>' />
If you like, you can change Eval("Width") to the expression that calculates the width.
You are going to want to handle the GridView's RowCreated event. This occurs just after the GridView creates each row and will give you programmatic access to the row and all the controls contained within it.
Here is the MSDN page on the event.
I suggest you to not use Eval, if you can, because it's a little slower. In that cases I generally prefer to cast my data source to his base type:
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Panel ID="bar" runat="server" Width='<%# ((yourCustomData)Container.DataItem).Width %>' />
</ItemTemplate>
</TemplateField>
</Columns>
where yourCustomData is the row type of your data source (i.e. the element of a List<>).
This method is really faster than Eval.
Edit: oh, don't forget to include in the page a reference to the namespace that contains yourCustomData
<%# Import Namespace="yourNameSpace.Data" %>
I suggest you attach a callback handler to the OnRowDataBound event. Each row binding will fire an event which you can handle in your callback handler.
In that callback handler, you can get the info about the item being bound to the row and apply the width according to the values in your database.