How do I do data binding with an ArrayList? Gives error.

A

Alan Silver

Hello,

I'm trying to use an ArrayList to do data binding, but am getting an
error I don't understand. I posted this in another thread, but that was
all confused with various other problems, which could be why no-one
answered it!! I've now narrowed the problem down, so am starting a new,
more specific, thread. Sorry it's a bit long, but it's reasonably simple
stuff.

I have a page where I'm showing product details, including any
non-priced variations available (say it comes in red, green and blue,
all at the same price), as well as any priced variations (say it comes
in small, medium and large, each at a different price).

I want to show the variation details in two repeaters, with all values
in editable controls. That way the user can edit as many as they like
without having to postback for each one.

I also have a set of controls where they can enter details for a new
variation. They click a link button and this creates an ArrayList
containing the variations from the existing repeater, plus the new one.
I then want to display this new list in the repeater. This is where I
get stuck ;-(

I have created a class for the variations as follows...

public class eCommVariation : IComparable {
public int avalueid; // the database ID
public string varName; // the displayed name (red, green, etc)
public bool showVar; // will this variation be shown?
public float price; // price (if a priced variation)
public bool specialOffer; // is it on special offer (if a priced
variation)
public float specialPrice; // special price (if a priced variation)

// method for IComparable so I can use the class for data binding
public int CompareTo(object objRhs) {
eCommVariation rhs = (eCommVariation)objRhs;
return String.Compare(this.varName, rhs.varName);
}
}

In the page itself, I pull the product details from a database when the
page first loads and display them. When the user clicks the "add new
variation" link button, the following code is called...

void lbtAddNpVar_Click(object o, EventArgs e) {
// add a new non-priced variation
// first set up the array of eCommVariation objects that will be used for databinding
ArrayList arrNpVars = new ArrayList();
// add the existing variations
for (int i=0; i<rptNpVars.Items.Count; i++) {
eCommVariation nPVar = new eCommVariation();
nPVar.avalueid = Convert.ToInt32(((Literal)rptNpVars.Items.FindControl("hidVarID")).Text);
nPVar.varName = ((TextBox)rptNpVars.Items.FindControl("txtNpVarName")).Text;
nPVar.showVar = ((CheckBox)rptNpVars.Items.FindControl("chkShowNpVar")).Checked;
// next three aren't relevant for non-priced variations, set them to dummy values
nPVar.price = 0;
nPVar.specialOffer = false;
nPVar.specialPrice = 0;
arrNpVars.Add(nPVar);
}
// now add the new value
eCommVariation newNpVar = new eCommVariation();
newNpVar.avalueid = 0; // shows it's a new value
newNpVar.varName = txtNewNpVar.Text;
newNpVar.showVar = chkShowNewNpVar.Checked;
// set the next three to anything as before
newNpVar.price = 0;
newNpVar.specialOffer = false;
newNpVar.specialPrice = 0;
arrNpVars.Add(newNpVar);
// so now we have the array of eCommVariation objects set up, sort it and bind it to the repeater
arrNpVars.Sort();
rptNpVars.DataSource = arrNpVars;
rptNpVars.DataBind();
}

(this code is for the non-priced variations, so the three class members
relevant to priced ones are just set to dummy values)

The problem is when the DataBind() method is called. The ItemTemplate of
the repeater looks like this (HTML simplified)...

<ItemTemplate>
<asp:CheckBox ID="chkDeleteNpVar" Text="" Checked="False" RunAt="server"/>
<br><asp:TextBox ID="txtNpVarName" Text='<%#DataBinder.Eval(Container.DataItem, "avalue")%>' Columns="20" MaxLength="20" cssClass="box"
RunAt="server" />
<br><span style="color:#ffffff"><asp:Literal ID="hidVarID" Text='<%#DataBinder.Eval(Container.DataItem, "avalueid")%>' RunAt="server" /></span>
<br><asp:CheckBox ID="chkShowNpVar" Text="" Checked='<%#TrueIfY((string)DataBinder.Eval(Container.DataItem, "show_avalue"))%>'
RunAt="server"/>
</ItemTemplate>

When it tries to do the data binding, it gives an error
"DataBinder.Eval: 'PixataWebUtils.eCommVariation' does not contain a
property with the name avalue" on the line...

<br><asp:TextBox ID="txtNpVarName"
Text='<%#DataBinder.Eval(Container.DataItem, "avalue")%>' Columns="20"
MaxLength="20" cssClass="box" RunAt="server" />

Now I know the class *does* contain a property (well, actually a public
variable, but I think that amounts to the same thing doesn't it?) with
the name "avalue". If I swap the order of the controls in the
ItemTemplate, then it gives the error on whichever comes first, so it's
not actually that the property doesn't exist, it's that it doesn't like
*any* of them.

What am I doing wrong here? It seems such a simple, basic thing that I'm
stuck. I know you can do data binding with an ArrayList, but I must be
missing some basic point here.

Any suggestions welcome. TIA.
 
K

Karl Seguin

Alan:
No, a public field doesn't amount to the same thing as a public property.
That's your problem, plain and simple. Besides, you shouldn't have public
fields...you should ALWAYS use properties.

BTW, I appreciate the detail of the post, but if no one answered your other
one, it might just be because of how long they are. I had to read
everything just to get to the bottom and get to the real root of the
problem. It's kinda a catch 22, sometimes we need more details and have to
ask for it, sometimes we get too much :) One thing that might have helped
is a simplified example. Your class could have contained just 2
fields...and your btn click could have been simplified just to create a
couple new instances of said class, added to an array list and binded. Just
some thoughts for the future :)

Karl


--
MY ASP.Net tutorials
http://www.openmymind.net/ - New and Improved (yes, the popup is annoying)
http://www.openmymind.net/faq.aspx - unofficial newsgroup FAQ (more to
come!)


Alan Silver said:
Hello,

I'm trying to use an ArrayList to do data binding, but am getting an
error I don't understand. I posted this in another thread, but that was
all confused with various other problems, which could be why no-one
answered it!! I've now narrowed the problem down, so am starting a new,
more specific, thread. Sorry it's a bit long, but it's reasonably simple
stuff.

I have a page where I'm showing product details, including any
non-priced variations available (say it comes in red, green and blue,
all at the same price), as well as any priced variations (say it comes
in small, medium and large, each at a different price).

I want to show the variation details in two repeaters, with all values
in editable controls. That way the user can edit as many as they like
without having to postback for each one.

I also have a set of controls where they can enter details for a new
variation. They click a link button and this creates an ArrayList
containing the variations from the existing repeater, plus the new one.
I then want to display this new list in the repeater. This is where I
get stuck ;-(

I have created a class for the variations as follows...

public class eCommVariation : IComparable {
public int avalueid; // the database ID
public string varName; // the displayed name (red, green, etc)
public bool showVar; // will this variation be shown?
public float price; // price (if a priced variation)
public bool specialOffer; // is it on special offer (if a priced
variation)
public float specialPrice; // special price (if a priced variation)

// method for IComparable so I can use the class for data binding
public int CompareTo(object objRhs) {
eCommVariation rhs = (eCommVariation)objRhs;
return String.Compare(this.varName, rhs.varName);
}
}

In the page itself, I pull the product details from a database when the
page first loads and display them. When the user clicks the "add new
variation" link button, the following code is called...

void lbtAddNpVar_Click(object o, EventArgs e) {
// add a new non-priced variation
// first set up the array of eCommVariation objects that will be used for
databinding
ArrayList arrNpVars = new ArrayList();
// add the existing variations
for (int i=0; i<rptNpVars.Items.Count; i++) {
eCommVariation nPVar = new eCommVariation();
nPVar.avalueid =
Convert.ToInt32(((Literal)rptNpVars.Items.FindControl("hidVarID")).Text);
nPVar.varName =
((TextBox)rptNpVars.Items.FindControl("txtNpVarName")).Text;
nPVar.showVar =
((CheckBox)rptNpVars.Items.FindControl("chkShowNpVar")).Checked;
// next three aren't relevant for non-priced variations, set them to
dummy values
nPVar.price = 0;
nPVar.specialOffer = false;
nPVar.specialPrice = 0;
arrNpVars.Add(nPVar);
}
// now add the new value
eCommVariation newNpVar = new eCommVariation();
newNpVar.avalueid = 0; // shows it's a new value
newNpVar.varName = txtNewNpVar.Text;
newNpVar.showVar = chkShowNewNpVar.Checked;
// set the next three to anything as before
newNpVar.price = 0;
newNpVar.specialOffer = false;
newNpVar.specialPrice = 0;
arrNpVars.Add(newNpVar);
// so now we have the array of eCommVariation objects set up, sort it and
bind it to the repeater
arrNpVars.Sort();
rptNpVars.DataSource = arrNpVars;
rptNpVars.DataBind();
}

(this code is for the non-priced variations, so the three class members
relevant to priced ones are just set to dummy values)

The problem is when the DataBind() method is called. The ItemTemplate of
the repeater looks like this (HTML simplified)...

<ItemTemplate>
<asp:CheckBox ID="chkDeleteNpVar" Text="" Checked="False" RunAt="server"/>
<br><asp:TextBox ID="txtNpVarName"
Text='<%#DataBinder.Eval(Container.DataItem, "avalue")%>' Columns="20"
MaxLength="20" cssClass="box"
RunAt="server" />
<br><span style="color:#ffffff"><asp:Literal ID="hidVarID"
Text='<%#DataBinder.Eval(Container.DataItem, "avalueid")%>' RunAt="server"
/></span>
<br><asp:CheckBox ID="chkShowNpVar" Text=""
Checked='<%#TrueIfY((string)DataBinder.Eval(Container.DataItem,
"show_avalue"))%>'
RunAt="server"/>
</ItemTemplate>

When it tries to do the data binding, it gives an error
"DataBinder.Eval: 'PixataWebUtils.eCommVariation' does not contain a
property with the name avalue" on the line...

<br><asp:TextBox ID="txtNpVarName"
Text='<%#DataBinder.Eval(Container.DataItem, "avalue")%>' Columns="20"
MaxLength="20" cssClass="box" RunAt="server" />

Now I know the class *does* contain a property (well, actually a public
variable, but I think that amounts to the same thing doesn't it?) with
the name "avalue". If I swap the order of the controls in the
ItemTemplate, then it gives the error on whichever comes first, so it's
not actually that the property doesn't exist, it's that it doesn't like
*any* of them.

What am I doing wrong here? It seems such a simple, basic thing that I'm
stuck. I know you can do data binding with an ArrayList, but I must be
missing some basic point here.

Any suggestions welcome. TIA.
 
A

Alan Silver

Alan:
No, a public field doesn't amount to the same thing as a public property.
That's your problem, plain and simple.

Duh, I knew it was going to be something simple. Thanks very much.
Besides, you shouldn't have public
fields...you should ALWAYS use properties.

I know, I was just being lazy ;-)

This class was for my personal use (being the only developer on this
site) and only for this page, so I figured (wrongly) I could take a
short-cut. I guess I'll know better next time eh?

Just out of interest, what is the difference between a public field and
a property? They look the same to the human eye, why does the framework
see them differently? Yes I am new at this, and yes I am trying to learn
to understand and do it right!!
BTW, I appreciate the detail of the post, but if no one answered your other
one, it might just be because of how long they are. I had to read
everything just to get to the bottom and get to the real root of the
problem.

Yeah, I know. I had the same thought when I posted it, but I couldn't
see how to simplify it without writing a new one (which I probably
should have done!!). I also get put off by long posts ;-)

Thanks very much for the help,

Alan
 
K

Karl Seguin

Fields vs Properties, it's actually the opposite. Properties are a lot more
like methods than fields. Actually, they are special methods. I'm not sure
why databinding only works against properties...I know you can reflect
against public fields (assuming databinding works by reflection)...I figure
it's just something they did out of convention - you aren't ever supposed to
have public fields anyways, so why would they support binding against them?
You want properties because it provides some encapsulation...if something
changes and ur using fields, you'll break code that's consuming yoru class.
Using properties, there's a good chance you'll be able to encapsulate the
change and calling code will be ignorant of the fact..

Karl
 
A

Alan Silver

Karl,

Thanks for the clarification. Reading your words made a lot of sense. I
did some Java a few years back and got quite into OOP, but then I spent
several years since doing only VB, so the principles got weak.

I guess I just need to learn not be so lazy!!

Ta ra
a
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top