Eval versus DataField in ASP:Datagrid - asp.net

I have this really random problem with is bugging me. It works at the end of the day but the problem took some time to figure out and was wondering why this happens so if anyone shed some light on the subject I would be really grateful. Here is the problem
I have the following two columns on my datagrid
<asp:boundcolumn
datafield="contentsection.Id"
headerstyle-cssclass="dgHead"
headertext="Section"
itemstyle-cssclass="dgItem" />
and
<asp:templatecolumn>
<itemtemplate><%#Eval("contentsection.Id") %></itemtemplate>
</asp:templatecolumn>
The first column gives me the error of:
A field or property with the name 'contentsection.Id' was not found on the selected data source
but the second on runs fine. Any ideas or theories as to why this is happening ?
The way that I call and bind my data is like so:
Page Load Code Behind
ContentList.DataSource = ContentBlockManager.GetList();
ContentList.DataBind();
The GetList() function it is overloaded and by default passed a 0
public static List<ContentBlockMini> GetList(int SectionId)
{
List<ContentBlockMini> myList = null;
SqlParameter[] parameters = { new SqlParameter("#ContentSectionId", SectionId) };
using (DataTableReader DataReader = DataAccess.GetDataTableReader("dbo.contentblock_get", parameters))
{
if (DataReader.HasRows)
{
myList = new List<ContentBlockMini>();
}
while (DataReader.Read())
{
myList.Add(FillMiniDataRecord(DataReader));
}
}
return myList;
}
and my filling of the data record. The ContentSection is another Object Which is a property of the ContentBlock object
private static ContentBlockMini FillMiniDataRecord(IDataRecord DataRecord)
{
ContentBlockMini contentblock = new ContentBlockMini();
contentblock.Id = DataRecord.GetInt32(DataRecord.GetOrdinal("Id"));
contentblock.Name = DataRecord.GetString(DataRecord.GetOrdinal("Name"));
contentblock.SEOKeywords = DataRecord.IsDBNull(DataRecord.GetOrdinal("SEOKeywords")) ? string.Empty : DataRecord.GetString(DataRecord.GetOrdinal("SEOKeywords"));
contentblock.SEODescription = DataRecord.IsDBNull(DataRecord.GetOrdinal("SEODescription")) ? string.Empty : DataRecord.GetString(DataRecord.GetOrdinal("SEODescription"));
if (DataRecord.GetInt32(DataRecord.GetOrdinal("ContentSectionId")) > 0)
{
ContentSection cs = new ContentSection();
cs.Id = DataRecord.GetInt32(DataRecord.GetOrdinal("ContentSectionId"));
cs.Name = DataRecord.IsDBNull(DataRecord.GetOrdinal("ContentSectionName")) ? string.Empty : DataRecord.GetString(DataRecord.GetOrdinal("ContentSectionName"));
contentblock.contentsection = cs;
}
return contentblock;
}
There you go that is pretty much the start to end.

Databinding can only access "top level" properties on an object. For example, if my object is
Company with simple properties CompanyId and Name and a child object for Address, databinding can only access CompanyId and Name, not Company.Address.City.
Eval can access child object properties if you import the namespace using an #Import page directive.

The "Bind" marker is a two-way bind and is made using the default namespace attached to the datasource of the object. This can't be overridden, and because of this tightly coupled connection the namespace should be left off as assumed (since it's dynamically pulled from the datasource).
Eval is a one-way binding that can be used with any namespace that will fulfill a proper evaluation. Dates, strings, method calls, etc. The namespace provided in your example just provides eval with a marker on where to get the data relevant.
The key here is the nature of the binding. Eval is a "fire and forget" sort of binding where as Bind is more rigid to facilitate the two-way.

The DataField property approach isn't complicated enough to support dot notation; it expects a direct reference in your underlying data source; it takes that field and checks the data source, which it can't find it by the exact string.
The second approach, eval, is more dynamic, but actually I wasn't sure if it supported dot notation... learn something everyday.
HTH.

It's necessary take a look to your DataSource, but you can do a simple test: convert the first column to a template column a try to Run.
In EntityFramework is possible Eval Properties using code like this: <%#Eval("Customer.Address.PostalCode") %>.
I dont know if it is your case, but if you provide more details about how to retrieve the DataSource we can help you.

Related

Displaying of the data in the gridview based on the search criteria using generics concept of .net

i am new to .net..i have to develop an asp.net application.
The UI of the web page will have a Data-bound Grid control on the Home page and there will be a Textbox where users can enter their search criteria.
I know to do this by using ado.net concept...
But i am supposed to do it using generics concept.How can i store the values in the generic list or dictionary of .net and filter the data based on the text entered in the text box.
Please help me out..
Thanks in advance..
You can indeed bind a GridView to List<T>, I do it all the time, like this:
Create a POCO for the data
public class SomeData
{
public string SomeField {get;set;}
public string SomeOtherField {get;set;}
}
Build the list (either manually or as a result a DB query) e.g.
var mylist = new List<SomeData>();
var myitem = new SomeData()
{
SomeField = "Hello",
SomeOtherField = "World"
};
To Filter the data do something like this:
myfilter = MyTextBox.Value;
mylist = mylist.Where(somedata => somedata.SomeField.Equals(myfiltervalue)).ToList();
Bind it to the GridView
mygridview.DataSource = mylist;
mygridview.DataBind();
And this is it!!
I assume you know ado.net and how to bind gridview.
You just need to iterate through your database resultset and add it to list and bind it.
Following link might help you to begin with:
http://www.aspsnippets.com/Articles/How-to-bind-GridView-with-Generic-List-in-ASPNet-using-C-and-VBNet.aspx
Pass your textbox value to your database query/stored procedure as parameter and return the result based on search value.
Edit:
You may want to use FindAll, Find method.
Check below link:
http://msdn.microsoft.com/en-us/library/aa701359(VS.80).aspx

Assign Business entity to hidden variable

Say for example if I have a business entity -> Customer, which has customerId, customerName and customerType. I have created an asp:Hidden Variable hdnCustomer to runat="server"
If I wanted to serialize the value of the customer business entity (in the code behind) to the hdnCustomer then how would I do that? Also once serialized how would I deserialize it?
// Pseudo code
Collection<Customer> customerList = new Collection<Customer>();
customerList = BusinessAccess.GetCustomerList();
hdnCustomer = serialize and assign the value of 'customerList' to hdnCustomer;
...
...
// Later on a select index change of one of the drop down lists
Inside the event handler for the drop down list:
{
Collection<Customer> customerList = new Collection<Customer>();
customerList = deserialize the value from hdnCustomer
int a = Convert.ToInt32(ddlDropDown.SelectedValue);
foreach(a in customerList)
{
// Do something
}
}
You can serialise to and from XML using XmlSerializer:
http://support.microsoft.com/kb/815813
However, if you just store the object in the ViewState[] collection that should work better:
ViewState["Customer"] = customerList;
It does the same thing: store the serialisable object in the page, hidden from the user: but it won't be in a human-readable format.
(edit: To deserialise, just get the value of ViewState["Customer"], checking for a null before using it!)
edit 2: a useful link about storing objects in ViewState:
http://www.beansoftware.com/ASP.NET-Tutorials/ViewState-In-ASP.NET.aspx
Hope that helps.
I think .net has already providing some classes to do so, look at this example

ActionScript 3 Object to name value string

In a Flex application I am trying to turn an Object into a QueryString such as name1=value1&name2=value2... But I am having trouble getting the names of the Objects children. How do I enumerate the names instead of the values?
Thanks
I'm guessing you're doing a for each(in) loop. Just do a normal for(in) loop and you'll get the names instead of the values:
for(var name:String in obj) {
var value:* = obj[name];
// do whatever you need
}
Ok, first off, if you need that query string to actually query a server, you don't really need to get it yourself as this code will query the server for you
protected function callSerivce():void
{
var o:Object = new Object();
o.action = "loadBogusData";
o.val1 = "dsadasd";
service.send(o);
}
<mx:HTTPService id="service" url="http://www.somewhere.com/file.php" method="GET" showBusyCursor="true"/>
Will make a call to the server like this: http://www.somewhere.com/file.php?action=loadBogusData&val1=dsadasd
But in case you really want to analyze the object by hand, try using ObjectUtil.getClassInfo, it returns a lot of information including all the fields (read more on LiveDocs).

MultiValue Parameter

I'm working on a web application that renders a reporting services report as a PDF and one of my requirements is to allow for multiple locations to be included on the same report. To handle this, I have created a multi-value report parameter which seems to do the trick when using the RS UI, etc. But, I am using the webservice for reporting services and cannot for the life of me figure out how to set the value of the parameter to be identified as having multiple values.
I've tried simply setting it as "LOC1,LOC2", but that is being picked up as a single value. I have also tried "LOC1" + System.Environment.NewLine + "Loc2".
You can send it through as a comma-delimited string if you're willing to parse it on the other end. A lot of languages have a String.Split(",") style method you can use for that.
Either that, or you can construct an array (or list, or collection) and pass that through as the parameter, though this would involve changing the contract on the webservice method.
Figured it out, you have to each value separately under the same name, snippet:
//Register parameters
ArrayList<ParameterValue> parmValues;
for(Map.Entry<String,String> entry:reportParams.entrySet()) {
//is it multi-value?
if(entry.getValue().contains(",")) {
//yes, add multiple ParameterValues under the same name
// with each different value
for(String mval:entry.getValue().split(",")) {
ParameterValue pv = new ParameterValue();
pv.setName(entry.getKey());
pv.setValue(mval.trim());
parmValues.add(pv);
}
} else {
//no, just a single value
ParameterValue pv = new ParameterValue();
pv.setName(entry.getKey());
pv.setValue(entry.getValue());
parmValues.add(pv);
}
}

Accessing the object/row being edited in Dynamic Data

I'm modifying the "Edit.aspx" default page template used by ASP.NET Dynamic Data and adding some additional controls. I know that I can find the type of object being edited by looking at DetailsDataSource.GetTable().EntityType, but how can I see the actual object itself? Also, can I change the properties of the object and tell the data context to submit those changes?
Maybe you have found a solution already, however I'd like to share my expresience on this.
It turned out to be a great pita, but I've managed to obtain the editing row. I had to extract the DetailsDataSource WhereParameters and then create a query in runtime.
The code below works for tables with a single primary key. If you have compound keys, I guess, it will require modifications:
Parameter param = null;
foreach(object item in (DetailsDataSource.WhereParameters[0] as DynamicQueryStringParameter).GetWhereParameters(DetailsDataSource)) {
param = (Parameter)item;
break;
}
IQueryable query = DetailsDataSource.GetTable().GetQuery();
ParameterExpression lambdaArgument = Expression.Parameter(query.ElementType, "");
object paramValue = Convert.ChangeType(param.DefaultValue, param.Type);
Expression compareExpr = Expression.Equal(
Expression.Property(lambdaArgument, param.Name),
Expression.Constant(paramValue)
);
Expression lambda = Expression.Lambda(compareExpr, lambdaArgument);
Expression filteredQuery = Expression.Call(typeof(Queryable), "Where", new Type[] { query.ElementType }, query.Expression, lambda);
var WANTED = query.Provider.CreateQuery(filteredQuery).Cast<object>().FirstOrDefault<object>();
If it's a DD object you may be able to use FieldTemplateUserControl.FindFieldTemplate(controlId). Then if you need to you can cast it as an ITextControl to manipulate data.
Otherwise, try using this extension method to find the child control:
public static T FindControl<T>(this Control startingControl, string id) where T : Control
{
T found = startingControl.FindControl(id) as T;
if (found == null)
{
found = FindChildControl<T>(startingControl, id);
}
return found;
}
I found another solution, the other ones did not work.
In my case, I've copied Edit.aspx in /CustomPages/Devices/
Where Devices is the name of the table for which I want this custom behaviour.
Add this in Edit.aspx -> Page_Init()
DetailsDataSource.Selected += entityDataSource_Selected;
Add this in Edit.aspx :
protected void entityDataSource_Selected(object sender, EntityDataSourceSelectedEventArgs e)
{
Device device = e.Results.Cast<Device>().First();
// you have the object/row being edited !
}
Just change Device to your own table name.

Resources