Environment is an oldish application written in ASP 2.0.
I have this code that displays a DB source into an ASP:repeater:
<asp:Repeater ID="Repeater" runat="server" DataSourceID="DS" OnItemDataBound="On_Repeater_ItemDataBound">
<ItemTemplate>
<asp:CheckBox ID="CB" runat="server" Text='<%# Eval("My_DB_Field") %>'></asp:CheckBox>
</ItemTemplate>
</asp:Repeater>
It works fine.
However, I would like to change the code so that sometimes CB.Text = My_DB_Field (as now) and sometimes it equals an other DB field value.
So I will need to do that into code behind's On_Repeater_ItemDataBound method.
But how can I access the template item DB fields inside this method?
In other words, what is the equivalent of
Text='<%# Eval("My_DB_Field") %>'
in code behind?
I see that what I am looking for can be accessed via:
((System.Data.DataRowView)(e.Item.DataItem)).Row.ItemArray[12]
However, Row.ItemArray is an object[]
So it looks extremely hazardous to hard-code the DB field ID (12).
I'd like to know if there is a dictionary like object so I can access it via the DB field name ("My_DB_Field")?
You can use DataBinder.Eval
string value = DataBinder.Eval(e.Item.DataItem, "My_DB_Field").ToString();
or
DataRowView row = e.Item.DataItem as DataRowView;
string value = row["My_DB_Field"].ToString();
Related
Problem: I'm trying to get a value from a HiddenField object and set it to a string. A value of "foo" is being returned as "foo, foo".
Details:
I have a Nested Gridview, and I'm trying to make the child Gridview editable. I have a method GetChildQuery(string id) which form the sql query to get the data for the Child Gridview, and I have the id bound to a HiddenField object in the HTML as so:
<asp:Gridview ID="gvChild" runat="server" AutoGenerateColumns="false" OnRowEditing = "gvChild_RowEditing">
<Columns>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:Label runat="server" ID="lblNameChild" Text='<% Eval("Name")%>'></asp:Label>
<asp:HiddenField runat="server" ID="hidIDChild" Value ='<%# Bind("ItemID") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:Label runat="server" ID="lblNameChildEdit" Text='<% Eval("Name")%>'></asp:Label>
<asp:HiddenField runat="server" ID="hidIDChildEdit" Value ='<%# Bind("ItemID") %>' />
</EditItemTemplate>
</asp:TemplateField>
and I try to access it in the OnRowEditing method like:
protected void gvhild_RowEditing(object sender, GridViewEditEventArgs e) {
Gridview child = sender as Gridview;
string itemID = (child.Rows[e.NewEditIndex].FindControl("hidIDChild") as HiddenField).Value.ToString();
string sql = GetChildQuery(itemID);
child.EditIndex = e.NewEditIndex;
child.DataSource = GetData(sql);
child.DataBind();
}
The id is used in the WHERE clause of my SQL query, and therefore the output is incorrect if the value of the id is incorrect. I don't know I this problem is occurring because of how I bind data to the HiddenField or how I'm calling it from the RowEditing method, or something I'm completely overlooking.
Ref: To make the Nested Gridview, I mainly followed https://www.aspsnippets.com/Articles/Nested-GridView-Example-in-ASPNet-using-C-and-VBNet.aspx and https://www.aspforums.net/Threads/133072/Edit-Update-Delete-in-Nested-Child-GridView-in-ASPNet/ which has the general format for my GetData method as well.
EDIT: Problem subverted by replacing the string itemID instantiation to
string itemID= ((child.Rows[e.NewEditIndex].FindControl("hidIDChild") as HiddenField).Value.Split(','))[0].ToString();
essentially splitting the duplication, accessing the first element, converting that to a string, and setting that equal to y string itemID.
However while this subverts the problem, I would still appreciate anyone's feedback as to why the problem is occurring in the first place. Thanks!
You should look at your rendered html.
When dealing with one gridview there is only ever one row open for editing at a time. And within a row's TemplateField the ItemTemplate and EditTemplate are mutually exclusive, that is to say that, when rendered, you will see only one or the other.
Likewise in the code behind, you will only have access to either the ItemTemplate row or the EditTemplate row depending on which event you process on postback.
The same rules apply to a nested/child Gridview.
So for the case you describe, I assume you are trying to use some ID from the parent to build a query to populate the child. If so I do not believe you need any hidden fields at all. This ID fieldname from the parents query should be set in the DataKeyNames property of the parent gridview.
You should then be able to pass the value to the procedure you are building for the child as
protected void gvhild_RowEditing(object sender, GridViewEditEventArgs e) {
string sql = GetChildQuery(gvParent.SelectedDataKey.Value);
child.DataSource = GetData(sql);
child.DataBind();
// Given that you have just populated the child I do not think the
// following is accurate, but that's for you to decide
child.SetEditRow(e.NewEditIndex);
}
Hope this helps.
I am coding Gridview programmatically.
I have dataset in code behind part(.cs),when i am trying to access the dataset in .aspx page using Eval() "Error Creating Control" error is coming.
Is it the Right way using Eval()?
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblGridTier" runat="server" Text='<%#Eval(dt.Tables[0].Columns["Tier"])%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
If you are doing something like this in the code behind to bind the GridView (and you actually should do something like this):
DateSet ds = ...
GridView1.DataSource = ds;
GridView1.DataBind();
then the correct way to use eval is to give it just the name of the column you want to show.
Text='<%#Eval("Tier")%>'
ok please note html is rendered first then your code behind file is called. Now here dataset is null (not yet created) when HTML is being rendered dataset is null so control will not be created and an exception will be thrown. You can use this work around on Page_Load you can set text property of label or check here if dataset is null then don't assign value using Eval. Hope it will help.
Eval function evaluates fields directly from the selected table of datasource which your grid is bound with. A couple of examples as follows:
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblSomeField" runat="server" Text='<%# Eval("field1")%>'></asp:Label>
<asp:Image ID="lblImageLink" runat="server" ImageUrl='<%# Eval("imagefield", "http://somelink.com/images/{0}")%>' />
<asp:HyperLink ID="lblMember" runat="server" NavigateUrl='<%# "/member.aspx?id=" + Eval("id") %>' Text='<%# Eval("membername") %>'></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
List<MasterBook> listOfBooks = new List<MasterBook>();
after i put the masterbook objects which by the way have 3 fields( name,id and active ) into the list
GridView1.DataSource = listOfBooks;
GridView1.DataBind();
in the web form
<Columns>
<asp:TemplateField HeaderText="Book Name">
<ItemTemplate>
<asp:Label ID="BookNameText" runat="server"
Text="<%#Container.DataItem%>">
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
the problem is that i want to display the bookmaster's name in the gridview column
this code print bookmaster in the column how can i make it type the name
Change:
<%#Container.DataItem%>
To:
<%#Eval("name")%>
Cast it to MasterBook:
Text="<%# ((MasterBook) Container.DataItem).Name %>">
The quick, dirty hack workaround is to overload the ToString() method of your MasterBookclass in order to return that name. Commit seppuku afterwards if you do it.
The elegant and graceful way is to make an object datasource. That way you can bind the grid view's columns to the objects' properties. In the case of a DataList or other templated data controls, you can bind your objects' properties to the data control's child controls in their templates.
The middle path is in hutchonoid's answer: evaluate a property of the object, not the object itself.
Use this sintax:
<asp:Label ID="BookNameText" runat="server"
Text="<%# ((MasterBook)Container.DataItem).Name %>">
I am building a website for a class and have come across an error that I can not find the solution to. I have a dropdownlist on the page that displays the cutomer name and sets the selected value to the customer id selected from a sqldatasource (data tables from access database - fig1) (this works fine as I have tested it before I added the second sqldatasource). I add a datalist control to the page and a second sqldatasource for the datalist to bind to. I configured the datasource using the configure data source wizard as shown in fig2. I then use the wizard to test the data returned by the query and see that it works, the wizard shows that the data that I wanted is returned. So I bind the datalist to the data source and now the itemtemplate (in the html source view) contains data bound labels that will show the values:
Products.Name:
<asp:Label ID="Products_NameLabel" runat="server" Text='<%# Eval("Products.Name") %>' />
<br />
Technicians.Name:
<asp:Label ID="Technicians_NameLabel" runat="server" Text='<%# Eval("Technicians.Name") %>' />
<br />
Incidents.DateOpened:
<asp:Label ID="Incidents_DateOpenedLabel" runat="server" Text='<%# Eval("Incidents.DateOpened") %>' />
<br />
Incidents.DateClosed:
<asp:Label ID="Incidents_DateClosedLabel" runat="server" Text='<%# Eval("Incidents.DateClosed") %>' />
<br />
Incidents.Description:
<asp:Label ID="Incidents_DescriptionLabel" runat="server" Text='<%# Eval("Incidents.Description") %>' />
The labels are now bound to the data returned from the second source....or so it would seem. When I run it and select a customer that should return the data that is being selected in the sqldatasource select statement, my program crashes and gives this error:
DataBinding: 'System.Data.DataRowView' does not contain a property with the name 'Products'.
I do not understand why it is saying that the datarowview does not contain a column with that name when the sqldatasource clearly returns it when I test it in the wizard. Can anyone please help?
P.S. Sorry for the links to imgur...apparently you have to have a higher rep to post pictures
I tried this and the generated HTML was NOT prefixed with the table name like in your code.
I hand-added the table name and reproduced your error.
So, if you have duplicate column names like you do, you need to modify the SQL statement to use an alias:
Products.Name as Products_Name
I am using databinding to iterate through a recordset returned from the database, and one of those recordsets is a comma separated list of items - I'm trying to use a second repeater to display each of those items as a hyperlink. So far this is the code that I have:
<asp:Repeater ID="myRepeater" runat="server" DataSource='<%# DataBinder.Eval(Container.DataItem, "SomeList").ToString().Trim(',') %>'>
<ItemTemplate>
<a href='http://somesite/downloadattachment.aspx?itemid=<%# Container.ItemIndex %>'><%# Container.DataItem %></a>
</ItemTemplate>
</asp:Repeater>
The trouble is that so far there are 3 reasons why this doesnt work:
I get a server tag is not well formed error unless I remove the runat="server" - why is this? (And why does it work without the runat="server"?)
Container.DataItem Evaluates to an instance of System.Data.DataRowView - how do I get the current piece of the string that I split?
More importantly, this only seems to print out 1 Container.DataItem, even when I know there is a comma in the string I've given it - any ideas?
Instead of Eval(), for non-trivial scenarios I generally cast Container.DataItem to the type I want, and then act on it from there in a type-safe way.
The "not well formed" error is caused by the single-quotes around the parameter to Trim(). If you use single quotes on the outside of your attribute definition, you can't use them inside it. In cases like yours where a databinding definition has a lot of code in it, I often create a helper method (either inside a script runat=server for for MVC views and other inline-code-friendly cases, or in code-behind for traditional web forms apps) which handles the code I want to run. By refactoring into a method, it clarifies the HTML and sidesteps the lame single/double-quote restrictions.
Regardless of where you put the code, In your case, you want to:
cast Container.DataItem to DataRowView
extract the SomeList column value using the [] operator
call String.Split() on that string to turn your CSV string it into an array of strings
use that as a data source of your inner repeater
The code should look something like this:
<asp:Repeater ID="myRepeater" runat="server"
DataSource='<%# ((System.Data.DataRowView)Container.DataItem)["SomeList"].ToString().Split(new string[] {","}, StringSplitOptions.RemoveEmptyEntries)%>'>
<ItemTemplate>
<a href='http://somesite/downloadattachment.aspx?itemid=<%# Container.ItemIndex %>'>
<%# Container.DataItem %>
</a>
</ItemTemplate>
</asp:Repeater>
Did you specify the updatecommand, deletecommand to the sqldatasource?
Even if the proper parameters haven't been supplied, the affected rows will always be 0. If it has two parameters for the update command, two parameters have to be supplied through updatecommand.
For more information on this please check this URL: http://www.itpian.com/Coding/4774-Data-binding.aspx