Databinding repeater. Property not found - asp.net

Why am i getting the error that
DataBinding: _Default+Student does not contain a property called name.
This is my CodeBehind:
public class Student
{
public string name ="Name";
public string favouriteFood = "Favourite food";
public string hobby = "Hobby";
}
protected void Page_Load(object sender, EventArgs e)
{
Student nino = new Student();
nino.name = "nino";
nino.favouriteFood = "nachos";
nino.hobby = "dancing son";
Student madelene = new Student();
madelene.name = "madelene";
madelene.favouriteFood = "sushi";
madelene.hobby = "dancing casino";
Student baiba = new Student();
baiba.name = "baiba";
baiba.favouriteFood = "bitch soup";
baiba.hobby = "complaining";
ArrayList students = new ArrayList();
students.Add(madelene);
students.Add(nino);
students.Add(baiba);
testRepeater.DataSource = students;
testRepeater.DataBind();
}
This is the front:
<asp:Repeater runat="server" ID="testRepeater" >
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "name") %>' />"></asp:Label>
</ItemTemplate>
</asp:Repeater>

Convert the public variable name into a property like:
private string _name;
public string name
{
get
{
return _name??"Name";
}
set
{
_name = value;
}
}
It can be an auto property, if you dont need a default value ("Name") like:
public string name {get;set;}

Related

How can I Bind a List of custom class objects to a Gridview's Datasource (getting "A field or property ... not found on the ... data source")?

To avoid querying the Database on the first loading of the page, I want to populate a List of a custom class to the GridView.
I'm trying to do it this way:
protected void Page_Load(object sender, EventArgs e)
{
List<MoviesGridDisplayColumns> listStartupData = new List<MoviesGridDisplayColumns>();
MoviesGridDisplayColumns mgdc;
mgdc = new MoviesGridDisplayColumns();
mgdc.MovieTitle = "War of the Buttons";
mgdc.MPAARating = "PG";
mgdc.IMDBRating = 7.5;
mgdc.Minutes = 94;
mgdc.YearReleased = "1994";
listStartupData.Add(mgdc);
mgdc = new MoviesGridDisplayColumns();
mgdc.MovieTitle = "The Trip to Bountiful";
mgdc.MPAARating = "PG";
mgdc.IMDBRating = 7.5;
mgdc.Minutes = 108;
mgdc.YearReleased = "1985";
listStartupData.Add(mgdc);
. . .
GridView1.DataSource = listStartupData;
GridView1.DataBind();
...but on the penultimate line above I get:
"System.Web.HttpException HResult=0x80004005 Message=A field or
property with the name 'MovieTitle' was not found on the selected data
source."
The selected data source is the List of MoviesGridDisplayColumns objects, which does indeed have a MovieTitle member. So what gives?
The custom class is:
public class MoviesGridDisplayColumns
{
public string MovieTitle = string.Empty;
public double IMDBRating = 0.0;
public string MPAARating = string.Empty;
public string YearReleased = string.Empty;
public int Minutes;
}
...and the GridView appears in the .aspx file thus:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnDataBound="GridView1_DataBound" OnPreRender="GridView1_PreRender">
<Columns>
<asp:BoundField DataField="MovieTitle" HeaderText="MovieTitle" SortExpression="MovieTitle" />
<asp:BoundField DataField="IMDBRating" HeaderText="IMDBRating" SortExpression="IMDBRating" />
<asp:BoundField DataField="MPAARating" HeaderText="MPAARating" SortExpression="MPAARating" />
<asp:BoundField DataField="YearReleased" HeaderText="YearReleased" SortExpression="YearReleased" />
<asp:BoundField DataField="Minutes" HeaderText="Minutes" SortExpression="Minutes" />
</Columns>
</asp:GridView>
The fields in your class are missing the getter methods. You can change the MoviesGridDisplayColumns to the following.
public class MoviesGridDisplayColumns
{
public string MovieTitle { get; set; } = string.Empty;
public double IMDBRating { get; set; } = 0.0;
public string MPAARating { get; set; } = string.Empty;
public string YearReleased { get; set; } = string.Empty;
public int Minutes { get; set; }
}

Using ASPxComboBox with ASPxGridView, need to set initial value

I'm trying to use ASPxGridView to display a list of ASPxComboBox controls. Both the rows in the grid and the list of options in the combo boxes are populated from code. I'm having problems setting the initial value of the combo boxes.
I'm looking for it to look similar to the image below.
As you can see in the screenshot, I have been able to get both the grid view & the combo boxes to populate, but I can't figure out how to set the initial values of the combo boxes.
In the Init event of the inner combo boxes, there's no obvious property to retrieve the bound object.
I did find a couple other questions on StackOverflow, for which the answer was to add a bound property to the combo box. However, adding SelectedIndex='<%# Bind("Level") %>' to the declaration for InnerCombo gave me the error "Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control."
Here's what I have so far:
Testing.aspx:
<%# Page Title="" Language="C#" MasterPageFile="~/Light.master"
AutoEventWireup="true" CodeBehind="Testing.aspx.cs" Inherits="MyProject.Testing" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<dx:ASPxGridView ID="MyGridView" runat="server" KeyFieldName="Name">
<Columns>
<dx:GridViewDataColumn FieldName="Name" />
<dx:GridViewDataColumn FieldName="Level">
<DataItemTemplate>
<dx:ASPxComboBox
runat="server"
ID="InnerCombo"
ValueField="ID"
TextField="Desc"
ValueType="System.Int32"
OnInit="InnerCombo_Init" />
</DataItemTemplate>
</dx:GridViewDataColumn>
</Columns>
</dx:ASPxGridView>
<dx:ASPxButton runat="server" ID="btnSubmit" Text="Submit" OnClick="btnSubmit_Click" />
</asp:Content>
Testing.aspx.cs:
public partial class Testing : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.MyGridView.DataSource = GetDefaultSettings();
this.MyGridView.DataBind();
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
Debug.WriteLine("btnSubmit_Click");
for (int i = 0; i < MyGridView.VisibleRowCount; i++)
{
object[] row = (object[])MyGridView.GetRowValues(i, "Name", "Value");
// row[1] is null, but we can get the data by finding the combo box itself.
GridViewDataColumn col = (GridViewDataColumn)MyGridView.Columns["Value"];
ASPxComboBox innerCombo = (ASPxComboBox)MyGridView.FindRowCellTemplateControl(i, col, "InnerCombo");
Debug.WriteLine("{0} = {1}", row[0], innerCombo.Value);
}
}
protected void InnerCombo_Init(object sender, EventArgs e)
{
Debug.WriteLine("InnerCombo_Init");
ASPxComboBox innerCombo = sender as ASPxComboBox;
if (innerCombo != null)
{
innerCombo.DataSource = GetValues();
innerCombo.DataBind();
}
}
private static List<ValueClass> GetValues()
{
// Simple for testing; actual method will be database access.
return new List<ValueClass>()
{
new ValueClass(0, "Zero (default)"),
new ValueClass(1, "One"),
new ValueClass(2, "Two"),
new ValueClass(3, "Three"),
};
}
private static List<SettingClass> GetDefaultSettings()
{
// Simple for testing; actual method will be database access + post-processing.
return new List<SettingClass>()
{
new SettingClass("AA", 0),
new SettingClass("BB", 1),
new SettingClass("CC", 0),
};
}
public class ValueClass
{
public int ID { get; private set; }
public string Desc { get; private set; }
public ValueClass(int id, string desc)
{
this.ID = id;
this.Desc = desc;
}
}
public class SettingClass
{
public string Name { get; set; }
public int Value { get; set; }
public SettingClass(string name, int value)
{
this.Name = name;
this.Value = value;
}
}
}

Properties of WebUserControl are null in DataBind override

I have WebUserControl with DataBind override:
public partial class WebUserControl1 : System.Web.UI.UserControl
{
public object DataSource { get; set; }
public string Text { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
}
public override void DataBind()
{
// *** there when called, properties are null, why? ***
repeater2.DataSource = DataSource;
repeater2.DataBind();
}
}
This control is in repeater with declarative bounded properties:
<asp:Repeater ID="repeater" runat="server">
<ItemTemplate>
<WebUserControl1 runat="server" DataSource='<%# DataBinder.Eval(Container.DataItem, "levels") %>' Text='<%# DataBinder.Eval(Container.DataItem, "Text") %>' />
</ItemTemplate>
</asp:Repeater>
Now when i call DataBind() on repeater:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
... data query
repeater.DataSource = items;
repeater.DataBind();
}
}
in overriden control's DataBind() method i don't have properly setted properties DataSource and Text, they are null, why?
If you have only one repeater control in WebUserControl1, it is easier to bind that child repeater control in Repeater.ItemDataBound Event of Parent repeater.
Here is the sample -
ASPX
<asp:Repeater ID="ParentRepeater" runat="server" OnItemDataBound="ParentRepeater_ItemDataBound">
<ItemTemplate>
<asp:Label runat="server" ID="StreetLabel" /><br/>
<asp:Repeater ID="ChildRepeater" runat="server">
<ItemTemplate>
<asp:Label runat="server" ID="FirstNameLabel" />
<asp:Label runat="server" ID="LastNameLabel" />
</ItemTemplate>
</asp:Repeater><hr/>
</ItemTemplate>
</asp:Repeater>
Code Behind
public class Address
{
public int Id { get; set; }
public string Street { get; set; }
public List<User> Users { get; set; }
}
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ParentRepeater.DataSource = new List<Address>
{
new Address
{
Id = 1,
Street = "1st Street",
Users = new List<User>()
{
new User {Id = 1, FirstName = "John", LastName = "Doe"},
new User {Id = 1, FirstName = "Marry", LastName = "Doe"}
}
},
new Address
{
Id = 2,
Street = "2nd Street",
Users = new List<User>()
{
new User {Id = 1, FirstName = "Eric", LastName = "Newton"},
new User {Id = 1, FirstName = "John", LastName = "Newton"}
}
}
};
ParentRepeater.DataBind();
}
}
protected void ParentRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var address = e.Item.DataItem as Address;
var streetLabel = e.Item.FindControl("StreetLabel") as Label;
streetLabel.Text = address.Street;
var repeater = e.Item.FindControl("ChildRepeater") as Repeater;
repeater.ItemDataBound += ChildRepeater_ItemDataBound;
repeater.DataSource = address.Users;
repeater.DataBind();
}
}
protected void ChildRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var user = e.Item.DataItem as User;
var firstNameLabel = e.Item.FindControl("FirstNameLabel") as Label;
firstNameLabel.Text = user.FirstName;
var lastNameLabel = e.Item.FindControl("LastNameLabel") as Label;
lastNameLabel.Text = user.LastName;
}
}
Solution for Original Question
Delete public override void DataBind() event and bind repeaters2 inside PreRender event.
public partial class WebUserControl1 : System.Web.UI.UserControl
{
protected override void OnPreRender(EventArgs e)
{
repeater2.DataSource = DataSource;
repeater2.DataBind();
base.OnPreRender(e);
}
}

asp.net gridview binding to deeper property of specific type

my webside has a gridview
i bind it to a dataset recived from powershell
in this dataset are a lot of different data types.
everything is working fine but for one field i would like to bind a deeper property to the boundfield!
i bind it like this:
c#
GridViewAgentGroups.DataSource = dt;
GridViewAgentGroups.DataBind();
Markup
<asp:BoundField DataField="Name" HeaderText="Name" ReadOnly="True" />
<asp:BoundField HeaderText="Service" ReadOnly="True"
DataField="Identity" />
<asp:BoundField DataField="Description" HeaderText="Description"
ReadOnly="True" />
the boundfield of service binds to data of type: "Microsoft.Rtc.Rgs.Management.RgsIdentity"
it contains an instanceID and serviceID propertyand the serviceID contains a property fullName!
when i bind it directly like "DataField="Identity" it shows a very long string with the fullName included!
is there a way to only bind the fullName? like "DataField="Identity.ServiceID.FullName"? in xml? (this does not work :-)
Yes it is possible with TemplateFields but it depends upon the dataSource design too. Have a look at this sample:
Markup:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<%#Eval("Name") %>
<%#Eval("GroupName.Name") %>
<%#Eval("GroupName.RegionName.Name") %>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code behind:
public class Region
{
public string Name { get; set; }
}
public class Group
{
public string Name { get; set; }
private Region _region=new Region();
public Region RegionName { get { return _region; } set { _region = value; } }
}
public class Product
{
public string Name { get; set; }
private Group _groupName = new Group();
public Group GroupName { get { return _groupName; } set { _groupName = value; } }
}
public class Products : List<Product>
{
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Region reg1 = new Region() { Name = "North" };
Region reg2 = new Region() { Name = "East" };
Group group1 = new Group() { Name="Group1", RegionName=reg1 };
Group group2 = new Group() { Name = "Group2", RegionName=reg1 };
Group group3 = new Group() { Name = "Group3", RegionName = reg2 };
Products prod = new Products()
{
new Product(){ Name="Product1", GroupName=group1},
new Product(){ Name="Product1", GroupName=group2},
new Product(){ Name="Product2", GroupName=group3},
new Product(){ Name="Product3", GroupName=group1},
new Product(){ Name="Product2", GroupName=group2},
};
GridView1.DataSource = prod;
GridView1.DataBind();
}
}

Grid view binding

I am binding an Object datasource to a grid view. My object has a collection of items in one of the properties.Which is a List. How do I Loop thru this and bind the items to a column in GridView?.
Get the Collection from the object and bind it by using
myGridView.DataSource = myCollection;
myGridView.DataBind();
Edit: updated to call a method in the code behind to generate html markup for the collection.
In your aspx markup you could have something like the following:
<asp:GridView ID="myGridView" AutoGenerateColumns="False" runat="server">
<Columns>
<asp:BoundField HeaderText="Item Name" DataField="Name" />
<asp:TemplateField HeaderText="Collection Field">
<ItemTemplate>
<%# ((_Default)Page).GetHtmlForList(DataBinder.Eval(Container.DataItem, "List"))%>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
then in your code behind you could have something like this:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
myGridView.DataSource = GetCollection();
myGridView.DataBind();
}
}
public string GetHtmlForList(object value)
{
string html = "";
List<string> list = (List<string>)value;
foreach (string item in list)
html += item + "<br/>";
return html;
}
private List<MyClass> GetCollection()
{
List<MyClass> coll = new List<MyClass>();
coll.Add(new MyClass { Name = "First Item", List = new List<string>(new string[] { "1", "2", "3" }) });
coll.Add(new MyClass { Name = "Second Item", List = new List<string>(new string[] { "Apples", "Pears", "Oranges" }) });
coll.Add(new MyClass { Name = "Third Item", List = new List<string>(new string[] { "Red", "Green", "Blue" }) });
return coll;
}
}
public class MyClass
{
public string Name { get; set; }
public List<string> List { get; set; }
}
Could you not have a Repeater inside the Col. template, and simply bind your List to it in the RowDataBound?

Resources