Gridview DataKeyNames subclass property - asp.net

I have a gridview bound to a list of objects like so List<myObject>.
The object has property which is a child object - an Address object.
I want to add the PostCode property of the Address object to the gridview's DataKeyNames property like so: DataKeyNames="Id, Address.Postcode", but keep getting the error myObject does not contain a property with the name Address.Postcode (it does...)
Any ideas?
EDIT: To clarify, I cannot modify myObject so that it exposes the Postcode as a property like so: myObject.Postcode. The Postcode property needs to sit where it is in the Address object (myObject property).

No you can't do it like this, it should be like..
DataKeyNames="Id, Postcode"
You need to get the PostCode column in your datasource object which you are going to bind to your Gridview.

Related

Array in gridview

I have a string array data[].I need to bind this string array as datasource in gridview.
I have values in data array.
I write the code
gridview_forecast.DataSource = data;
gridview_forecast.DataBind();
I got an error as "A data item was not found in the container. The container must either implement IDataItemContainer, or have a property named DataItem."
You cannot directly assign an array to GridView DataSource when GridView.AutoGenerateColumns is False. One way to do this convert your array to ArrayList or DataTable,
then assign it to GridView DataSource.
For an example click here

ContextTextType and TableName for LinqDataSource when data source is List<string>

I have a LinqDataSource defined like this:
<asp:LinqDataSource ID="LinqDataSource1" runat="server" OnSelecting="LinqDataSource_FileSelecting"></asp:LinqDataSource>
In LinqDataSource_FileSelecting, it returns/sets a List<string> to e.Result, where e is the EventArgs (LinqDataSourceSelectEventArgs) in the Selecting event of the LinqDataSource. I'm getting this error when the page loads:
"The ContextTypeName property of LinqDataSource 'LinqDataSource1' must specify a data context type."
Based on this message and looking at the docs, I need to set the ContextTypeName and TableName properties of the LinqDataSource. ContextTypeName would normally be the name of a class, and TableName would be the name of an enumerable property within that class.
When the data source is a List<string> I'm not sure what ContextTypeName or TableName I can assign. I've tried System.Collections.Generic.List<string> for the ContextTypeName, but that didn't work, I received "Could not load type 'System.Collections.Generic.List<string>'"
I realize the LinqDataSource may not be the appropriate control when the data source is a List<string> generated within the Selecting event. But is there a ContextTypeName and TableName I can set for this scenario?
Found the answer. Turns out that you can omit ContextTypeName and TableName when using the Selecting event and assigning a List<string> to e.Result. However, if you assign null to e.Result, then this error will occur since ASP.NET doesn't know the type of data. My code on the Selecting event was designed to set a non-null value to e.Result, but a separate problem was leading to null being set to e.Result ... leading to this error.

Problem with getting selected OBJECT from dropdownlist

I have a problem with getting selected objectfrom my list.
I bind collection of users to dropdownlist by:
ddlContractors.DataSource = service.GetAllUsers();
ddlContractors.DataTextField = "Name";
ddlContractors.DataValueField = "Id";
ddlContractors.DataBind();
It's working.
But when I try getting selected object by:
var user = (User)ddlContractors.SelectedItem;
I get:
(User)ddlContractors.SelectedItem Cannot convert type 'System.Web.UI.WebControls.ListItem' to 'GWDSite.GWDService.User'
How can I get object user from dropdownlist ? I can change type of my list control if it is necessary
The value field in the dropdown list is the field "Id" not the User object. so 'SelectedItem' is returning the "Id" value -- not the object. You can use that Id to lookup the User object (from session or cache or wherever you can keep it)
You cant.
The SelectedItem is of type ListItem and you cannot just typecast a listItem back into your custom class i.e user.
You can only get the text or the value associated with the item that was selected via SelectedItem / SelectedValue
What you need to do is use that text / value and maybe retrieve your corresponding "User" object based on that text / value from somewhere (depending on how you are doing your state management).
use SelectedValue instead of SelectedItem
WEB APPLICATION
As you are working with web app , approach i was describng will not work here.
you can get the ID of the selected item and use this ID as a parameter to retrive the object from the service layer but if the object is expensive to create than use caching to store your object and retrive it wheb needed.

how to retrieve the other values in the business entity

The method has a return type of collection<businessEntity>. I am calling the method from the aspx page in order to populate a drop down -> ddlDropDown. I am binding he DataTextField of the ddlDropDown with the BusinessEntity.Name and the DataValueField with BusinessEntity.Id, the business entity contains another id which is BusinessEntity.ProductId. I need to use the ProductId of the value selected in the drop down list in the code behind. Can you help suggest how I can do so?
One possible way could be to call the method in the page_Load on the code behind and save the collection in a hidden variable and when required do a loop through in the hidden variable and retrieve the selected value Product Id.
Your thoughts please.
You could certainly accomplish this using a hidden field.
Here's another idea: bind the DataValueField to a special derived string, containing the BusinessEntity.Id AND the BusinessEntity.ProductId.
In other words, concatenate the BusinessEntity.Id and BusinessEntity.ProductId into a single string, seperated by the pipe ("|") symbol for example.
E.g to bind:
ddlFoo.DataValueField = string.Format("{0}|{1}", "Id", "ProductId");
Then to retrieve selected item:
var id = ddlFoo.SelectedValue.Split("|")[0];
var productId = ddlFoo.SelectedValue.Split("|")[1];
Saves you looping/matching. Again, its not ideal, but then again neither is binding multiple values types to a dropdownlist.

How to databind a property within a property

I cureently have a set up like below
Public ClassA
property _classB as ClassB
End Class
Public ClassB
property _someProperty as someProperty
End Class
what I want to do is to databind object A to a gridview with one of the columns being databound to ClassB._someProperty. When I try to databind it as Classb._someProperty I get a "Field or Property not found on Selected Datasource" error
I have tried to use the objectContainerDataSource and also directly binding to the gridview with no success.
Has anyone come across this in the past?
Ordinary databinding doesn't generally allow for expressions. Under the hood the datagrid is using reflection (rather the executing code the way DataBinder.Eval does on an ASP.NET page) to find the property that you specify to bind to a column. To do what you want it would need to evaluate the binding as an expression, work out that you were looking for a parent -> child relation, and then reflect down to that level. AFAIK the inbuilt databinding on the grid is too dumb to know how to do this.
I've had the same issue recently, and my solution was to do a LINQ projection and bind that to the grid instead. Something like the following (in C# because I'm not comfortable with the LINQ syntax in VB):
IList<ClassA> listOfClassAObjects = GetMyListOfClassAObjectsFromSomewhere();
var projection = from ClassA a in listOfClassAObjects
select new { SomeProperty = a.SomeProperty,
SomeOtherProperty = a.SomeOtherProperty,
SomePropertyFromB = a.ClassB.SomeProperty };
datagrid.DataSource = projection;
datagrid.DataBind();
You'll get back a list of anonymous types containing that projection, and you can bind the appropriate column to SomePropertyFromB.
For extra encapsulation (if you do this a lot) put the projection into an extension method so you can do something like
var data = GetMyListOfClassAObjectsFromSomewhere().ProjectionForDataGrid();
datagrid.DataSource = data;
datagrid.DataBind();
I found the way to do this is to use a template field and eval (see below)
Set the datafield as property classB and then:
<asp:TemplateField HeaderText="_someProperty">
<ItemTemplate>
<%#Eval("classB._someProperty")%>
</ItemTemplate>
</asp:TemplateField>

Resources