Databinding exception with entity navigation property - asp.net

I have two Entity classes: Order and OrderItem. Order contains a navigation property OrderItemSet of type
System.Data.Objects.DataClasses.EntityCollection<OrderItem>
On an aspx page is a FormView bound to this EntityDataSource:
<asp:EntityDataSource ID="EntityDataSourceOrder" runat="server"
ConnectionString="name=EntitiesContext"
DefaultContainerName="EntitiesContext"
EntitySetName="Order"
Include="OrderItemSet"
// stuff to define a query
</asp:EntityDataSource>
The FormView is bound to the DataSource and the ItemTemplate of this FormView contains a ListView which I try to bind to the OrderItemSet. It looks this way:
<asp:FormView ID="FormViewOrder" runat="server" DataKeyNames="OrderID"
DataSourceID="EntityDataSourceOrder" AllowPaging="True" >
<ItemTemplate>
...
<asp:ListView ID="ListViewOrderItems" runat="server"
DataSource='<%# Eval("OrderItemSet")%>' >
...
</asp:ListView>
</ItemTemplate>
</asp:FormView>
When I run the application I get an exception pointing to the line DataSource='<%# Eval("OrderItemSet")%>' in markup and telling me:
DataBinding: System.Web.UI.WebControls.EntityDataSourceWrapper does not contain a property with name 'OrderItemSet'
What is wrong here?
(I've done the same with other navigation properties which are not lists but single object references, and that works.)
Thank you for help!

It seems to me that you are trying to evaluate a collection from within a datasource, without first binding to that datasource.
Why don't you try binding directly to the datasource? E.g.
<asp:ListView ID="ListViewOrderItems" runat="server"
DataSourceID="EntityDataSourceOrder"
...
</asp:ListView>

Related

Nested CheckBoxList using DataSet and Repeaters

I'm trying to wire up some CBL's using a repeater and dataset. The dataset contains 2 tables with the same schema and a (one, single) relation (in SQL land think of it as a self join).
When the control is rendered if I set my DataSource = the relationship, I am able to get the children elements to show; so I know the model is good, although misplaced (on purpose to test the model - see code below).
The problem is:
I am having difficulty getting the parent elements to show up at all
Not all parents have children, and the ones that don't still need to show up
Am I approaching this in the right frame of mind? i.e. Am I missing something fundamental? Implementation outside of CBL(plain text) works fine per this article
<asp:Repeater ID="ParentRepeater" runat="server">
<ItemTemplate>
<asp:CheckBoxList ID="ParentCBL" runat="server"
DataSource='<%# DataBinder.Eval(Container.DataItem,"Joined") %>'
DataTextField="TextProperty"
DataValueField="ValueProperty">
</asp:CheckBoxList>
<asp:Repeater ID="ChildRepeater" runat="server">
<ItemTemplate>
<asp:CheckBoxList ID="ChildCBL" runat="server"
DataSource='<%# DataBinder.Eval(Container.DataItem, "Joined") %>'
DataTextField="TextProperty"
DataValueField="ValueProperty">
</asp:CheckBoxList>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
Page Load is nothing spectacular
DataSet ds = Foo.foo();
ParentRepeater.DataSource = ds.Tables["Parent"];
ParentRepeater.DataBind();
In your code you don't bind ChildRepeater
If you want just change plain text to Checkbox in according to https://support.microsoft.com/en-us/kb/306154
then you don't need to use CheckBoxList. But you should only use single checkbox inside repeater.

ASP 4.5 GridView Template Field with possible null object

I have a list of objects in my GridView where the child object could be null. I can't seem to get the right syntax to test for null and ignore/print empty string.
I see 3 possible answers for this:
This can be done easily in the aspx file in a declarative way
I have to do it in code behind
it can't be done like this and I need to sort out my list method and project a new one with no nulls, something like that.
Here is the grid view code, GetMyData is a method that just returns IEnumerable<MyClass> and this comes from EntityFramework where I'm using the Include method to eager load the Customer object.
<asp:GridView runat="server"
CssClass="listTable"
ItemType="MyClass"
DataKeyNames="ID"
SelectMethod="GetMyData"
AutoGenerateColumns="false"
AlternatingRowStyle-CssClass="listAlternate">
<Columns>
<asp:DynamicField DataField="ReferenceDate" />
<asp:TemplateField>
<ItemTemplate>
<%# (Item.Customer != null) ? Item.Customer .Name : ""; %>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Please note, I'm using entity framework 6.1 and .Net 4.5 in this project
Don't use ;
<asp:TemplateField>
<ItemTemplate>
<%# Eval("Item.Customer") != null ? Eval("Item.Customer.Name) : "" %>
</ItemTemplate>
</asp:TemplateField>

Data Binding Error in cascading Drop downs in asp.net

I have 2 drop down list within the edit item Template of a form view. The first drop down contains a lit of vehicle Makes and the second a list of Vehicle Models. The list of models needs to be filtered by the selection from the Makes drop down.
Here are the 2 Drop down List
<telerik:RadComboBox ID="RadComboBoxAssetMake" runat="server" DataTextField="AssetMakeName"
SelectedValue='<%# Bind("MakeId") %>' DataSourceID="odsAllAssetMakes" AutoPostBack="True" DataValueField="Id" Skin="Vista"
Width="212px" OnSelectedIndexChanged="RadComboBoxAssetMake_SelectedIndexChanged">
<telerik:Items>
<telerik:RadComboBoxItem Text="" Value="" />
</telerik:Items>
</telerik:RadComboBox>
<telerik:RadComboBox ID="RadComboBoxAssetModel" runat="server" DataTextField="AssetModelName"
SelectedValue='<%# Bind("ModelId") %>' DataSourceID="odsAssetModelByMake" DataValueField="Id" Skin="Vista" Width="212px">
<telerik:Items>
<telerik:RadComboBoxItem Text="" Value="" />
</telerik:Items>
</telerik:RadComboBox>
Initially I wanted to use a control select parameter on the object data source for the model Drop down. With the parameter getting the value from the Make drop down. However this doesn't seem to work as the select parameter on the object data source can't see the control with in the form view.
So now I am trying to use a session select parameter on the object data source.
<asp:ObjectDataSource runat="server" ID="odsAssetModelByMake" DataObjectTypeName="GPSO.Repository.AssetModel"
TypeName="GPSOnline.ATOMWebService" SelectMethod="GetAssetModelbyMake">
<SelectParameters>
<asp:SessionParameter DbType="Guid" SessionField="assetMakeId" Name="assetMakeId" />
</SelectParameters>
</asp:ObjectDataSource>
But now I get the this error "Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control." When I try to data bind the model drop down in the selected index changed method of the make drop down.
protected void RadComboBoxAssetMake_SelectedIndexChanged(object o, RadComboBoxSelectedIndexChangedEventArgs e)
{
Session["assetMakeId"] = e.Value.ToString();
((RadComboBox) fvAsset.FindControl("RadComboBoxAssetModel")).DataBind();
}
Is there a simple way to achieve this kind of thing, it would seem like such a common scenario that there must be a standard way to do it?
Initially I wanted to use a control select parameter on the object
data source for the model Drop down. With the parameter getting the
value from the Make drop down. However this doesn't seem to work as
the select parameter on the object data source can't see the control
with in the form view.
You need to move the ObjectDataSource into templates:
<EditItemTemplate>
<telerik:RadComboBox ....
<telerik:RadComboBox ....
<asp:ObjectDataSource ....
<asp:ObjectDataSource ....
</EditItemTemplate>

Moving repeater in form removes serverside declaration

I have two repeaters bound to object collections. They both work fine. But when I move repeater B to repeater A's FooterTemplate the serverside declaration of repeater B disappear.
This is not a parent/child relation.
Any ideas why this happens?
Update:
<asp:Repeater ID="myOuterRepeater" runat="server">
<ItemTemplate>
...
</ItemTemplate>
<FooterTemplate>
<asp:Repeater ID="myInnerRepeater" runat="server">
<ItemTemplate>
<asp:Button OnCommand="btnRemove_Click" ID="btnRemove" RunAt="server" />
<%#Eval("ItemId")%>
<%#String(Eval("Amount"))%>
<ItemTemplate>
</asp:Repeater>
</FooterTemplate>
</asp:Repeater>
When I bind:
myOuterRepeater.DataSource = myCollection
myOuterRepeater.DataBind()
Dim innerRepeater As Repeater =
myOuterRepeater.Controls(myOuterRepeater.Controls.Count - 1).Controls(0).FindControl("myInnerRepeater")
innerRepeater.DataSource = myInnerCollection
innerRepeater.DataBind()
When nesting a control (including a second repeater) inside a repeater, it is not longer part of the page but part of the enclosing repeater.
You will need to use FindControl(string) to get a reference to the nested repeater:
Repeater nested = enclosingRep.FindControl("nestedRepeaterId");

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

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!

Resources