How do I data bind a drop down list in a gridview from a database table using VB? - asp.net

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!

Related

Asp.net gridview edit without editbutton

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!

Using hyperlink with querystring for gridview row

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"]))
}
}

Dynamic Data - Selecting a table from a DropDownList to scaffold in a GridView

I have been struggling with this ASP.NET Dynamic Data problem for days now... I have a DropDownList containing the table names of all the tables in my data context (.dbml) file. When I select the DropDownList, it needs to scaffold the selected table in a GridView. My code works 100% in scaffolding the MetaTable in the GridView (it implements all the rules that I applied in my Meta Classes).
However, filtering only seems to work if I explicitly add the DynamicExpression in the declaration of the QueryExtender:
<asp:QueryExtender ID="GridQueryExtender" TargetControlID="GridDataSource" runat="server">
<asp:DynamicFilterExpression ControlID="FilterRepeater" />
</asp:QueryExtender>
This in turn requires me to specify the MetaTable explicitly in the LinqDataSource (linqdsData), either programmatically in the Page_Load or in the ASP.NET syntax.
Since the GridView gets scaffolded in the Page_Load part of the life-cycle, the above approach does not work for me, since it takes place in the Page_Init part of the life-cycle.
So my requirement is that as soon as I select another table to populate the GridView with from the DropDownList, the FilterRepeater needs to reflect the filters of the newly selected MetaTable.
Is there any way for me to programmatically update the FilterRepeater in the Page_Load so that it will contain the filters of the MetaTable that I selected in the DropDownList.
The following is some of my code:
ASP.NET Page Code-Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (ddlTable.SelectedIndex > 0)
{
string tableName = ddlDataType.SelectedValue;
linqdsData.TableName = tableName;
MetaTable mt = ASP.global_asax.DefaultModel.GetTable(tableName);
GridViewData.SetMetaTable(mt, mt.GetColumnValuesFromRoute(Context));
GridViewData.EnableDynamicData(mt.EntityType);
GridViewData.DataSourceID = linqdsData.ID;
}
}
ASP.NET Page:
<asp:Panel runat="server" ID="pnlFilters" CssClass="gridFilterCon" EnableTheming="True">
<div class="filterGridHeading">
Filter the grid by:</div>
<asp:QueryableFilterRepeater runat="server" ID="FilterRepeater">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("DisplayName") %>' OnPreRender="Label_PreRender"
CssClass="gridFilterLbl" />
<asp:DynamicFilter runat="server" ID="DynamicFilter" />
<br />
</ItemTemplate>
</asp:QueryableFilterRepeater>
<asp:Button ID="btnFilter" runat="server" Text="OK"
EnableTheming="False" UseSubmitBehavior="False" OnClick="btnFilter_Click" />
</asp:Panel>
<asp:GridView ID="GridViewData" runat="server" OnSelectedIndexChanged="GridViewData_SelectedIndexChanged"
OnPreRender="GridViewData_PreRender" OnRowDataBound="GridViewData_RowDataBound"
OnPageIndexChanged="GridViewData_PageIndexChanged" AllowPaging="True" PageSize="50" OnInit="GridViewData_Init">
<Columns>
...
</Columns>
<PagerTemplate>
<asp:GridViewPager ID="GridViewPager1" runat="server" />
</PagerTemplate>
<PagerSettings Mode="NumericFirstLast" NextPageText="Next" />
</asp:GridView>
<asp:LinqDataSource ID="linqdsData" runat="server" ContextTypeName="pdcDataContext"
OnSelected="linqdsData_Selected" OnSelecting="linqdsData_Selecting" EnableUpdate="True">
</asp:LinqDataSource>
<asp:QueryExtender ID="GridQueryExtender" TargetControlID="linqdsData" runat="server">
</asp:QueryExtender>
Your help will be greatly appreciated.
It sounds like you are trying to do a lot on one web page. This creates complications of the type you are experiencing: each table requires distinct filters and MetaTables. Trying to keep each item straight requires a bunch of switch and/or if...then statements. I recommend an alternate approach. Instead of doing all of this on one page:
Create a web page for each table
Setup the appropriate filters and MetaTables
Copy the DropDownList containing the table names of all the tables to each web page, and use it to redirect to the appropriate web page.
ASP.net Dynamic Data makes it easy to create web pages for each table. That is what scaffolding is all about. With the approach above, each web page will handle its own set of concerns that are focused on the particular table.
Hope this helps.

Gridview custom paging inside wizard control doesn't work correct in asp.net

I have a page where guests can be selected.
This page contains an update panel, within the update panel there is a wizard control and in the wizard control there is a gridview (Panel-> Update Panel -> wizard control -> gridview)
Now the paging doesn't work well, I searched the internet for answers but I didn't find the right answer. I use custom paging.
When I want to change the pagenumber (to the second or last page) it works fine. But when I want to select a row or go to another page, the gridview doesn't work correct. When I select A row on the second or last page (other page's don't work) the selected guest (item) is always one of the first page. When I want change to another page (from the second or last page) it doesn't work and stays on the selected page.
Is there a way to solve this problem?
part of the code:
<asp:Panel ID="PnlRe" Style="display: none; ... >
<asp:UpdatePanel ID="UpdtPnlDetail" runat="server" UpdateMode="Conditional">
<ContentTemplate>
...
<asp:Wizard ID="wzd" runat="server" ... >
...
<asp:WizardStep ID="WizardStep3" runat="server" Title="Naam">
...
<asp:Gridview ID="Gridview1" runat="server" AutoGenerateColumns="False"
DataKeyNames="GastID,Versie" DataSourceID="odsGasten" EmptyDataText="...."
OnRowCommand="Gridview1_RowCommand" OnPageIndexChanging="Gridview1_PageIndexChanging"
OnPageSizeChanging="Gridview1_PageSizeChanging" OnSearching="Gridview1_Searching"
OnSorting="Gridview1_Sorting" OnRowDataBound="Gridview1_RowDataBound"
CausesValidation="False" meta:resourcekey="..." PagerType="Custom"
ShowFilter="True" ShowInsertRecord="True" ShowPageSizer="True" UseSubmitBehaviour="False">
<Columns>
<asp:TemplateField ShowHeader="False" meta:resourcekey="...">
<ItemTemplate>
<asp:ImageButton runat="server" CommandName="Select" CausesValidation="False" SkinID="uprowbutton"
ToolTip="..." ID="ImgBtnSelect" meta:resourcekey="...">
</asp:ImageButton>
</ItemTemplate>
</asp:TemplateField>
... Boundfields ...
</Columns>
</asp:Gridview>
...
</asp:WizardStep>
...
</asp:Wizard>
</ContentTemplate>
</asp:UpdatePanel>
protected void Gridview1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
this.odsGasten.FilterExpression = searchText;
this.Gridview1.DataBind();
this.UpdtPnlDetail.Update();
}
there is a tricky way to achieve this, you have to manipulate your data source.
for example if you are using a datatable you have to select first ten elements of dt and bind it to grid, and when next button is clicked get next ten elements of dt and bind it to gridview. this will make your task easy and will get more performance for your page.
I can see that this.GridView1.DataBind() is called in GridView1_PageIndexChanging, but where is the currentPageIndex stored and updated with the page index you want to navigate to and when in the process is it happening?
Sounds to me like you have a viewstate problem.
You need to make sure that between Init and Load you have the grid's source set, either from viewstate or from a new bind-ing.

ASP .Net Gridview bind to data only when clicking update

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.

Resources