ASP Gridview - Column that either displays button or text - c#

I have a Gridview that works like a timetable. There are 3 Columns in the gridview.
Columns are as below
From
Till
Reservate
I want to have a button on the reservate column as long as the spot is free. If the spot is taken I want to display some text instead.
Currently I am using below markup
<asp:TemplateField HeaderText="Kranbeladung - Crane loading">
<ItemTemplate>
<asp:Button ID="rBtn" runat="server" Text="Reservate" />
</ItemTemplate>
</asp:TemplateField>
Any idea how I can achieve that?
Thanks

Greg answer is great but I had to do some changes. With his code I got this in my page:
System.Web.UI.WebControls.Button
instead of the Control itself.
In order to work I returned the HTML of the Cotrol, like that:
protected string CheckAvailability(object obj)
{
//some logic
return "<asp:Button runat='server'>ButtonText</asp:Button>";
}

Since you have a trigger, you would have a method that would test the column. Then populate according to the result. Below is what you would have in your Grid.
<asp:TemplateField HeaderText="...">
<ItemTemplate>
<%# CheckAvailability(Eval("Column")) %>
</ItemTemplate>
</asp:TemplateField>
Then you would do the following in code behind:
protected Control CheckAvailability(object flag)
{
if(flag != null)
{
// Create a button, then return it.
}
else
{
// Create a label, say space available and return.
}
}

Related

ASP.NET DataGrid is empty

I have a ASP.NET datagrid which is on a user control. I have a main page which adds the user control ( sometimes multiple copies of the user control ) and restores them when a post back occurs.
The dataGrid has insert / edit / delete links. I can add multiple copies of the user control to the page and the insert / edit delete functionality works perfectly for each separate control.
Yesterday I added some property binding to the main page to which are unrelated to the user control using the format Text='<%# DocumentTitle %>'. Initially I couldn't get this to work until I added Page.DataBind(); to the main page's Page_Load method. At this point the property binding started working correctly but then I noticed the insert functionality had stopped working in the datagrid within each user control....I debugged and found that when the following line executes it finds the text fields in the controls within the dataGrid to be empty or "":
eInfo.Ref = ((TextBox)gvEG.FooterRow.FindControl("txtEmployeeName")).Text;
If I remove the page.DataBind() method from the main page then the property binding stops working but the dataGrid(s) in the userControl start working.
My question is two fold i) Why does the seemingly unrelated change effect the dataGrid and ii) what do I do to get this working?
I've added the relevant sections of my code below...or at least what I think are the relevant sections.
Default.aspx
<div class="general">
<asp:TextBox Width="488" runat="server" placeholder="Document Title" Text='<%# DocumentTitle %>'></asp:TextBox>
</div>
Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Create an empty user control for the first requirements section.
EmployeeSectionUserControl myUserControl1 = (EmployeeSectionUserControl )LoadControl("~/EmployeeSectionUserControl .ascx");
// Add it to the panel control holding all the user controls.
MainPanel.Controls.Add(myUserControl1);
DocumentTitle = "I am the default document title and I'm bound.";
}
else
{
// Do nothing
}
Page.DataBind();
}
EmployeeSectionUserControl.ascx
<asp:GridView ID="gvEG" runat="server" AutoGenerateColumns="False" CssClass="grid"
AlternatingRowStyle-CssClass="gridAltRow" RowStyle-CssClass="gridRow" ShowFooter="True"
EditRowStyle-CssClass="gridEditRow" FooterStyle-CssClass="gridFooterRow" OnRowCancelingEdit="gvEG_RowCancelingEdit"
OnRowCommand="gvEG_RowCommand" OnRowDataBound="gvEG_RowDataBound" OnRowDeleting="gvEG_RowDeleting"
OnRowEditing="gvEG_RowEditing" OnRowUpdating="gvEG_RowUpdating" DataKeyNames="Id" ShowHeaderWhenEmpty="true">
<Columns>
<asp:TemplateField HeaderText="Id" HeaderStyle-HorizontalAlign="Left" ControlStyle-Width="50px">
<ItemTemplate>
<%# Eval("Id")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Ref" HeaderStyle-HorizontalAlign="Left" ControlStyle-Width="90px">
<EditItemTemplate>
<asp:TextBox ID="txtEmployeeName" runat="server" Text='<%# Bind("Ref") %>'
Width="90px"></asp:TextBox>
</EditItemTemplate>
<FooterTemplate>
<asp:TextBox ID="txtEmployeeName" runat="server" Width="90px"></asp:TextBox>
</FooterTemplate>
EmployeeSectionUserControl.ascx.cs
protected void gvEG_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.Equals("Insert"))
{
employeeInfo eInfo = new employeeInfo();
eInfo.Id = 999;// Convert.ToInt32(((TextBox)gvEG.FooterRow.FindControl("Id")).Text);
// If we're inserting from the EmptyDataTemplate( ie an empty table ) of the gridview then we need to retreive the data differently.
// So we perform a check on the gridView FooterRow and if it's null then we can assume it's an empty table.
if (gvEG.FooterRow == null)
{
TextBox referenceTxtBox = (((Control)e.CommandSource).NamingContainer).FindControl("txtEmployeeName") as TextBox;
eInfo.Ref = referenceTxtBox.Text;
}
else
{
eInfo.Ref = ((TextBox)gvEG.FooterRow.FindControl("txtEmployeeName")).Text;
eInfo.Need =
}
// Store Update and Re-bind data to grid.
}
}
Page.DataBind() calls DataBind on it's children, so it updates DocumentTitle in the text box but it also DataBinds your grid. I didn't see a DataSource set in your grid, like an EntityDataSource, so I am assuming you are doing the smart retrieving (and preparation) of the data yourself in code and set the DataSource yourself:
gvEg.DataSource = someCollection;
gvEg.DataBind();
On the get your are loading the user-control and probably call this DataBind with specifying the DataSource. It binds and then you call Page.DataBind() which probably also triggers another DataBind for gvEg but since DataSource is set it shows the same.
On the post back you shouldn't do a DataBind() before handling events. Your call of Page.DataBind() does that. It triggers a DataBind() without a DataSource. Then the rowCommand comes and checks for the TextBox in the Footer which is cleared due to a DataBind with no elements.
What you should do is:
You shouldn't use Page.DataBind(). If you do so, you need todo it at a moment when all DataSources are set correctly and it shouldn't be kicked of during a post back. In general, I would not recommend using it because it makes it more complex and it's probably only helping a bit if you haven't set up your application correctly.
In your case it's definitely not necessary. Your textBox is a server control that's not part of any binding (GridView, Repeater, ListView). So your textBox is immediately available in your code behind.
So you should:
Give the textBox an ID you can use like txtDocumentTitle
<asp:TextBox Width="488" ID="txtDocumentTitle" runat="server" placeholder="Document Title"></asp:TextBox>
Replace setting DocumentTitle (unless you need it for something else too) with:
txtDocumentTitle.Text = "I am the default document title and I'm bound.";
Remove Page.DataBind();
So access server controls you have access immediately since they are also properties in your page or control.

Rowdeleteing event in Gridview

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.

Import checked status from a function

I'm trying to make this code work:
<asp:CheckBox ID="statusChk" runat="server" Visible="true" Enabled="false" Checked='<%# status("de_cancel") %>'></asp:CheckBox>
What i'm trying to do is to retrieve the answer from the status function (which returns bool when i give a string) that i created in the c# source.
Doesn't give me compile error, but doesn't work. Edit: And btw, this is inside in a GridView
This works:
<asp:Label ID="lblInfo" runat="server" Visible="true" Text='<%# Bind("de_cancel") %>'></asp:Label>
But this is NOT what I'm looking for.
Sorry about my bad English.
I'm assuming that this is in a grid view, or some other repeater.
In that case, try this:
<asp:Label ID="lblInfo" runat="server" Visible="true" Text='<%# status(Eval("de_cancel")) %>'></asp:Label>
this is essentially calling your status() method and passing in the value of de_cancel
You may have to convert de_cancel inside your status method though as Eval returns an object.
Just do this in the codebehind:
protected void Page_Load(object sender, EventArgs e)
{
//Get your string variable and use it as input here
statusChk.Checked = status("de_cancel");
}
protected bool status(string strStatus)
{
if (strStatus == "de_cancel")
{
return true;
}
else
{
return false;
}
}
This will occur when the page loads. There are other event handlers you may want to use - see http://msdn.microsoft.com/en-us/library/6w2tb12s(v=vs.90).aspx
Here is an example of how an event handler (OnSelectedIndexChanged) can be used to set a checkbox when a drop-down value is changed. As the accepted answer points out, you will need to set the AutoPostBack="true" option on the control if you want the event handler method to fire (and the page to refresh) when a control is changed:
Getting a dropdownlist to check a checkbox in asp.net/C#
Also, just looking at your code it looks like you might be using databinding, e.g. with a Repeater or ListView. In this case, please the examples for the ItemDataBound event handler below:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listview.itemdatabound(v=vs.110).aspx
http://www.codeguru.com/csharp/.net/net_asp/tutorials/article.php/c12065/ASPNET-Tip-Use-the-ItemDataBound-Event-of-a-Repeater.htm
Thanks to Darren tip, i was able to do it. Here what i did to make it work:
<asp:CheckBox ID="statusChk" runat="server" Visible="true" Enabled="false" Checked='<%#status(Convert.ToString(Eval("de_cancel")))%>'></asp:CheckBox>
Thanks everyone. ;)

ASP.net C# Gridview ButtonField onclick event

I've written an ASP code for a webshop type project. There is a method that adds the ProductID to a cookie and adds 1 to the quantity of the product.
Another method reads the cookie, transforms the cookie to a data table and puts it in a gridview. This gridview basically is the shoppingcart.aspx page.
What i now need is a way to add a buttonfield to that gridview where i can add a ++ button (like the add to shopping cart button on a product page), normal asp buttons take a onclick="methodname" but these in the gridview don't.
add1ToShoppingCart(string productId)
{[...]shoppingCartCookie[productId] = (amount + 1).ToString();}
That is the code I use for all the ++ buttons. It takes the button.id (buttonID=productID). So I need a way to have all the buttons be the same image, but the buttonID has to be databound to the productID so it can somehow execute that method (with some sort of onclick="").
I've looked and googled for the past couple hours but I cant seem to find anything. In the past I found a lot of answers on stackoverflow so I hoped somebody here could help.
Thanks in advance.
you can use Template field :
<asp:TemplateField ItemStyle-Width="33px" ItemStyle-HorizontalAlign="Center" ItemStyle-VerticalAlign="Middle"
ShowHeader="false" HeaderStyle-Height="40px">
<ItemTemplate>
<asp:ImageButton ID="btnAddToCard" runat="server" ImageUrl="~/Images/btnAddToCard.png" CausesValidation="false"
CommandName="AddToCard" CommandArgument='<%# Eval("ID") %>'
/>
</ItemTemplate>
<HeaderStyle Height="40px"></HeaderStyle>
<ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="33px"></ItemStyle>
</asp:TemplateField>
and in your C# code behind you create the following event of your gridview and do what you want :
protected void GV_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "AddToCard")
{
//Write code to add to card
}
}
GV is the ID of my GridView !

How to get selected value for dropdown list inside gridview?

Scenarios
I am using DataGrid with a column containing DropDownList. When I update the values, the DropDownList value does not get updated.
My Research so far
I believe it needs some C# code to made the DropDownList editable. I don't know where to put the code and how? Is there a shorter way than C# code?
Thank you very much
Edit : Supplied Code
student_table : id, name, major, favorite_teacher
teacher_table : id, name
The gridview has datasource of student. The DropDownList has datasource of teacher.
In the gridview with, I have made favorite_teacher as template field (DropDownList) and has teacher_table as datasource. In the edit mode, the DropDownList shows correct and populates teachers from the teacher table. When I select a favourite teacher for any student and click submit, the submit does not go through. I might need some C# code or otherwise. Don't know how to fix this problem.
Please try the below code and let me know if it's fixed:
protected void btnClick_Click(object sender, EventArgs e)
{
var tmpValue = ((DropDownList)gvRowItem.Cells[/*cellId*/].FindControl("/*dropDownListId*/")).SelectedValue;
}
You can try the following code
DataSourceID="sds_teacher_table" is referring to the teacher_table. the gridview will be referring to the student_table
<asp:TemplateField HeaderText="Favourite Teacher" >
<ItemTemplate>
<asp:Label ID="lblfavorite_teacher" runat="server" Text='<%# LookupTeacherName(DataBinder.Eval(Container.DataItem, "id")) %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlfavorite_teacher" runat="server" DataSourceID="sds_teacher_table" DataTextField="name" DataValueField="id" SelectedValue='<%#Bind("id")%>' Width="98%">
</asp:DropDownList>
</EditItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="ddlNewfavorite_teacher" runat="server" DataSourceID="sds_teacher_table" DataTextField="name" DataValueField="id" SelectedValue='<%#Bind("id")%>' Width="95%">
</asp:DropDownList>
</FooterTemplate>
<ItemStyle Width="25%" />
</asp:TemplateField>
protected string LookupTeacherName(object idObj)
{
if (string.IsNullOrEmpty(idObj.ToString()))
return null;
string TeacherId = idObj.ToString();
// find the corresponding name
IEnumerator enumos = sds_teacher_table.Select(new DataSourceSelectArguments()).GetEnumerator();
while (enumos.MoveNext())
{
DataRowView row = enumos.Current as DataRowView;
if ((string)row["id"].ToString() == TeacherId)
return string.Concat(row["name"].ToString());
}
return TeacherId;
}
I implemented this from a tutorial here without writing any C# code.
You do not need C# code, although you can implement it using C# code as well.
There is a trick that you have to implement. You need to bind the values of gridview to a datasource of the other table that you want to fetch data from. But by design, since dropdown list is contained in GridView, it can only be bound to gridview fields. This is the main complication.
To overcome that, include those additional fields in the gridview. You may need to use join statement so that you can include all the fields that you need in gridview. Now you can easily bind those fields to DropDownlist. Of course you do not need to show these extra values in GridView, they are there only for DropDownList. This will solve your problem, without writing a single line of code.

Categories

Resources