Here's how I want the control to work. Click edit on a row in gridview. There's a textbox in one of the columns, I would like it to be blank even though there's data in the database for that column, but when I click update I would like whatever new text the user entered to update the database for that column. It would be one-way databinding, but the other way?
Here's how I did it using an sql datasource with the select,update and delete methods generated.
First, you'll need to make any column that you want to edit like this a template field with an item template and and edit item template:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" DataSourceID="SqlDataSource1"
onrowupdating="GridView1_RowUpdating">
<Columns>
<asp:TemplateField HeaderText="City" SortExpression="City">
<ItemTemplate>
<asp:Label runat="server" Text='<%# Eval("City") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="txtCityEdit" Text=""></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Next handle the gridview's on update event:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
//find the value control who's value you want
TextBox tb = (TextBox)GridView1.Rows[e.RowIndex].FindControl("txtCityEdit");
//since we are not using a bound column for city we need to explicitly insert the value
//into the update parameter.
SqlDataSource1.UpdateParameters["City"].DefaultValue = tb.Text;
}
Even if you are using something other than an SQL Datasource this should be the basic solution.
// Find notes textbox
TextBox tb = (TextBox)MyActiveReferrals.Rows[e.RowIndex].FindControl("NotesTextBox");
e.NewValues.Add("Notes", tb.Text);
I used a linq data source.
Related
I have regular asp.net gridview,and i want to enable editmode in each row,and also without editbutton (like excel grid).
Edited data i want to save to my database by clicking "Post" button outside the grid(one button for whole grid).
How can i reach it?
To achieve this, you are going to have to use ItemTemplates for each column with textboxes in them as the control..
ASP
<asp:TemplateField HeaderText="Heading Title" SortExpression="Heading Title">
<ItemTemplate>
<asp:TextBox ID="tbTextbox" runat="server" Width="65px" Text='<%# Bind("ColumnNameYouWantToView") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
After this is set up properly, you will want the post button. You can either put it in the grid or outside the grid. I use both, but here is the one inside the grid as a footer.
ASP
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnView" runat="server" Text="View" OnClick="btnView_Click" Width="40px" />
</ItemTemplate>
<FooterTemplate>
<asp:Button ValidationGroup="UPDATE" ID="btnUpdate" OnClick="btnUpdate_Click" runat="server" Text="Update" Width="50px"></asp:Button>
</FooterTemplate>
<FooterStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="50px" />
</asp:TemplateField>
So far, what I have found that works best is using a foreach statement in your button click. The biggest flaw with this idea is that it will update every single row. It works, but if you only change a single row at a time, it will update all of them. I have my pager set to 10, so 10 rows are always updated (unless you are just searching for a single record and update it, the only that single record is updated).
Code Behind C#
protected void btnUpdate_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["databaseConnection"].ConnectionString);
conn.Open();
//finds the controls within the gridview and updates them
foreach (GridViewRow gvr in gvGridViewName.Rows)
{
string ID = (gvr.FindControl("lblId") as Label).Text.Trim();//finds the control in the gridview
string anotherControl = ((TextBox)gvr.FindControl("tbTextBox")).Text.Trim();//finds the textbox in the gridview
//Your update or insert statements
}
This is how I do it. You can also look into Real World Grids but I haven't had much luck with this as I would always get an error if a textbox was empty. This however, is suppose to be "smart" enough to just update the rows that have been changed, but again, I didn't have much luck of doing it this way. Hope this helps!
Is there someway to turn the row of a gridview into a hyperlink so that when a user opens it in a new tab for example, it goes to that link? Right now I am using a LinkButton and when the user opens it in a new tab, it doesn't know where to go.
I figured the .aspx code would look something like:
<asp:TemplateField>
<ItemTemplate>
<Hyperlink ID="hyperlink" runat="server" ForeColor="red" HtmlEncode="false" navigationURL="testUrl.aspx"
</ItemTemplate>
</asp:TemplateField>
The only thing is, our URLs are set up in the C# code behind as a query string, so I'm not sure how to pass that into the navigationURL section.
I'm guessing there's something I can do on the page_load with the query string to redirect to the page I need, but this is my first time working with query strings so I'm a little confused.
Thanks!
<asp:TemplateField>
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%#String.Format("~/controller.aspx?routeID1={0}&routeID2={1}", Eval("routeid1"), Eval("routeid2"))%>'></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
routeid1 and routeid2 are passed as query strings to the controller of that page.
What I did recently is modified my class to have a readonly property that constructs the A tag for me. This way I have control over what gets displayed; just text or a link.
<ItemTemplate>
<asp:Label ID="ColumnItem_Title" runat="server" Text='<%# Bind("DownloadATag") %>'> </asp:Label>
</ItemTemplate>
The code behind just binds an instance of the class to the gridview. You can bind the gridview whenever, on load on postback event, etc.
Dim docs As DocViewList = GetViewList()
GridViewDocuments.DataSource = docs
GridViewDocuments.DataBind()
In the above code, the DocViewList, instantiated as docs, is a list of a class that has all the properties that are needed to fill my GridView, which is named GridViewDocuments here. Once you set the DataSource of your GridView, you can bind any of the source's properties to an item.
Something like:
<asp:LinkButton ID="LinkButton_Title" runat="server" target="_blank"
PostBackUrl='<%# Eval(Request.QueryString["title"]) %>'
or binding them from the RowCreated event:
protected void GridView_OnRowCreated(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
(e.Row.FindControl("LinkButton_Title") as LinkButton).PostBackUrl = Request.QueryString["title"]))
}
}
I have multiple textboxes and dropdown lists within my GridView. For one particular textbox I need trigger a server event which gets data from the database and fills it in other columns of the Grid. Is there a simple way to do it or a slightly complicated way as detailed here
I have no problems implementing the above method or thinking of a work around but then thought that there is Cell Lost Focus in a grid control surprises me a little. Am I missing something ? Any help on this would appreciated.
You can set AutoPostBack to true and handle it's TextChanged event.
<asp:GridView ID="GridView1" runat="server" EmptyDataText="It's Empty.">
<Columns>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:TextBox ID="txtName"
runat="server"
Text='<%#Eval("Name") %>'
AutoPostBack="true"
OnTextChanged="NameChanged" >
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</GridView>
in codebehind:
protected void NameChanged(Object sender, EventArgs e)
{
var txtName = (TextBox) sender;
var row = (GridViewRow) txtName.NamingContainer;
// you could find other controls in this GridViewRow via
// row.FindControl("ControlID") in case of a TemplateField or
// row.Cells[0].Text (0 = index of column) in case of a BoundField
}
I have a Gridview which contains some controls which are updated from the server when the user makes a selection from a gridview.
After making their selection from a drop down list the user can enter a percentage into a textbox on a row and I have some javascript which then carries out some calculations and outputs to a span within an item template in the Gridview.
This all works but if the user then makes another drop down list selection on any row all the spans in the gridview are reset to blank (I've tried with various controls, both asp.net and html).
This is all inside an Update Panel.
Code:
<asp:GridView runat="server" ID="gdvIngredients" AutoGenerateColumns="false" CssClass="table table-stripped"
GridLines="None" Visible="false" ShowFooter="true" EnableViewState="true">
<Columns>
<asp:TemplateField Visible="false">
<ItemTemplate>
<asp:Label runat="server" ID="lblId" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Ingredient" ItemStyle-Width="12%">
<ItemTemplate>
<asp:DropDownList runat="server" ID="ddlName" AutoPostBack="true" OnSelectedIndexChanged="ddlName_SelectedIndexChanged"
ForeColor="Black" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="%" ItemStyle-Width="6%">
<ItemTemplate>
<asp:TextBox runat="server" Text="0" Width="50px" ID="txtPercentage" onkeyup="calculate(this);"
ForeColor="Black" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="kj" ItemStyle-Width="6%">
<ItemTemplate>
<asp:Label runat="server" ID="lblKj" CssClass="Kj" Style="display: none;" />
<span runat="server" id="spnKj" class="NewKj">0</span>
</ItemTemplate>
From your question what i have understood is that you are doing calculation in javascript and assigning it to span,but when next postback happens the value is not retained...If i am right i would suggest you to try the following steps.Use HiddenFields also to assign Values as HiddenFields Retain values during PostBacks.
Add Hidden field in Item Template
Set "calculate" function to Textbox from Codebehind(from rowdatabound event) & also pass the currosponding HiddenField Value to it as calculate(this,'HiddenFieldId');
protected void grd_RowDataBound(object sender,GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
HiddenField hdn = ((HiddenField)e.Row.FindControl("HiddenFieldID"));
TextBox txtPercentage = (TextBox)e.Row.FindControl("txtPercentage");
HtmlGenericControl spnKj=(HtmlGenericControl )e.Row.FindControl("spnKj");
txtPercentage.Attributes["onClick"]="calculate(this,'"+hdn .ClientID+"');"
spnKj.innerHTML=hdn.Value;
}
}
Javascript:
Assign Calculated Value to Hidden Field...
function calculate(hdnID)
{
var CalcValue=//do your Calculation
document.getElementByID(hdnID).Value=CalcValue;
}
3.In the DropDown PostBack Event Bind the GridView Again.
The above code should take care of the Issue You are facing.
You can use the "AutoPostBack" property to control the Postback event of some controls.
Have a look if your dropdown list selection do any PostBack.
If it does, then span values disappear, becuase Span is not ASP.NET webcontrol. After pages is postback, asp.net webcontrol values are restored from ViewState. So, spans doesn't have ViewState and no values are restored.
You can try to change your tag to
<span runat="server" id="spanIDHere">SomeValue here</span>
runat="server" makes span to be HtmlGenericControl and maintains its ViewState.
Span values would not be saved after postback if you update them using Javascript. You should call server-side function to update span values or try to use Hidden fields to store your values.
So in this gridview, there is a column for status and I want to have a drop down list with Pass, Pending, Fail appear when the edit button is clicked. These values are already in a table, so I need to somehow bind from this table to each ddl for every row.
Here is the column from the gridview. As you can see, I would like to just have a label showing when not in edit mode, and a ddl when the edit button is pressed
<asp:TemplateField HeaderText="During Production Status" SortExpression="DuringProductionStatus">
<EditItemTemplate>
<asp:DropDownList ID="ddlStatus" runat="server" datavaluefield="Name"
datatextfield="Name" DataSource="*What goes here?*"> />
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblStatus" runat="server"
Text='I don't understand how to get this from the ddl' />
</ItemTemplate>
</asp:TemplateField>
For clarity's sake, my table is named Status, and the database is named DirectImport
There's a few steps to go through here - none of them are particularly difficult, but they can be a bit fiddly (IMHO). The good news is once you've got this working once, it gets easier to do it again!
I'm assuming you've got a <asp:*DataSource> control on your page - my preference is for an ObjectDataSource but I don't think it matters, I think a SqlDataSource works equally well. I've never tried doing this with GridView.DataSource = MyDataSet in code-behind, so I don't know whether that would work or not, but my assumption is that it wouldn't as you wouldn't get the proper two-way binding that you want. This data source feeds your grid with your main data. The key point here is that your database query must return both the Status text field and the Status id.
So your gridview will now look something like:
<asp:objectdatasource runat="server" id="MainDataSource" ... />
<asp:gridview runat="server" id="MyGridView" DataSourceID="MainDataSource">
<Columns>
<asp:TemplateField HeaderText="During Production Status" SortExpression="DuringProductionStatus">
<ItemTemplate>
<asp:Label ID="lblStatus" runat="server"
Text="<%# Bind('Status') %>" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:gridview>
The Text="<%# Bind('Status') %>" is the bit you're missing to get the status text into the grid.
Now add a second data source into your markup that reads in the set of values from the Status table.
<asp:objectdatasource runat="server" id="StatusObjectDataSource" ... />
And add the EditItemTemplate into the GridView, which is bound to the Status DataSource.
<EditItemTemplate>
<asp:DropDownList ID="ddlStatus" runat="server" datavaluefield="StatusID"
datatextfield="Status" DataSourceID="StatusObjectDataSource"
SelectedValue="<%# Bind('StatusId') %>" />
</EditItemTemplate>
The SelectedValue="<%# Bind('StatusId') %>" is what connects up the two datasets so that when you flip a row into Edit mode, the dropdownlist has the correct item already selected, and when you then save it you've got the Status ID to put into your database.
And you're done.
I have used the RowDataBound event. Here is a small code snippet. HTH
you would have an ItemTemplate in your aspx/ascx
<asp:TemplateField HeaderText="Column Headings">
<ItemTemplate>
<asp:DropDownList ID="ddlName" runat="server" Width="150"></asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
and in your code behind, you will have
protected void grdDataMap_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddl = (DropDownList)e.Row.FindControl("ddlName");
ddl.DataSource = someList;//the source of your dropdown
ddl.DataBind();
}
}
so when you bind your grid with grdDataMap.Databind (assuming your grid id is grdDataMap), row databound event will be called for each row (including header/footer, and thats the reason you check RowType)
so you can probably decide what controls/columns to hide/show/bind inside this row databound event
In the winforms world I pull my objects from the DB into a List(Of Whatever) and use the list as the datasource.
This also lets me add extra "convenience" fields in the object so that I can populate it with stuff from other tables.
I don't know asp.net at all so if you can do something similar, it might help.
A really quick solution is to create a custom web control for the status dropdown. The control will always contain the same data. When it renders you populate the datasource. When it gets added to the gridview, the data will be in the drop down. Hope that helps!