Is it possible to have the datasource of a asp.net repeater be a list<string> that is a property of a class? - asp.net

Here is the aspx for my repeater:
<asp:Repeater ID="rpt_Files" runat="server">
<HeaderTemplate>
<th><asp:Label runat="server" ID="lbl_FileNameHeader" Text="File Name" /></th>
</HeaderTemplate>
<ItemTemplate>
<asp:Label runat="server" ID="lbl_FileName" Text='<%# Eval("JobFileNames") %>' />
</ItemTemplate>
</asp:Repeater>
Here is the code for binding the data in C#:
rpt_Files.DataSource = CurrentQuote;
rpt_Files.DataBind();
And here is the class definition of CurrentQuote:
public class CurrentQuote
{
// Properties
private List<string> _jobfilenames;
public List<string> JobFileNames
{
get
{
if (_jobfilenames != null)
return _jobfilenames;
else
{
_jobfilenames = new List<string>();
return _jobfilenames;
}
}
set { _jobfilenames = value; }
}
Here is the error I receive:
An invalid data source is being used for rpt_Files. A valid data source must implement either IListSource or IEnumerable.
If I change the repeaters datasource to CurrentQuote.JobFileNames I receive an error stating that string has no property called "JobFileNames".

If you have one quote with multiple files your DataSource should look something like this:
CurrentQuote cq = new CurrentQuote();
string[] filenames = new string[] { "file1", "file2", "file3" };
cq.JobFileNames = filenames.ToList();
rpt_Files.DataSource = cq.JobFileNames;
rpt_Files.DataBind();
Then in the markup you can use:
<asp:Label runat="server" ID="lbl_FileName" Text='<%# Container.DataItem %>' />
So yes "It is possible to have the datasource of a asp.net repeater be a list that is a property of a class" but you should instantiate the class first and from markup you have to access directly the DataItem since it is a string.

You should assign DataSource to a List of objects like this:
List<CurrentQuote> myCurrentQuoteList = new List<CurrentQuote>();
CurrentQuote currentQuoteObj = new CurrentQuote();
currentQuoteObj.JobFileNames.Add("test");
myCurrentQuoteList.Add(myCurrentQuoteList );
rpt_Files.DataSource = myCurrentQuoteList;
rpt_Files.DataBind();
You cannot directly assign a class Object, you should implement IListSource or IEnumerable to be used as your data source.

Related

Usercontrol in EditItemTemplate of templated control. How to achieve two-way databinding?

I was hoping to replace the EditItemTemplate of an ASP.NET ListView with a user control but I can't work out how to bind it to the data item in the ListView to achieve two-way data binding. The data item isn't a simple property. It's an object.
This seems only to give one-way Eval type databinding:
<EditItemTemplate>
<uc:MyUserControl id="thecontrol" runat="server" TheObject='<%# Container.DataItem %>'/>
</EditItemTemplate>
This gives an error:
<EditItemTemplate>
<uc:MyUserControl id="thecontrol" runat="server" TheObject='<%# Bind("Container.DataItem") %>'/>
</EditItemTemplate>
As does this:
<EditItemTemplate>
<uc:MyUserControl id="thecontrol" runat="server" TheObject='<%# Bind("this") %>'/>
</EditItemTemplate>
Is there some binding expression syntax to give two-way databinding to the current item in an EditItemTemplate?
Edit. This is the user control:
public partial class EditItemUserControl : System.Web.UI.UserControl
{
public TestObject TheObject
{
get
{
return new TestObject() { ID = Int32.Parse(hfID.Value), Name = txtName.Text };
}
set
{
hfID.Value = value.ID.ToString();
txtName.Text = value.Name;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
Just for reference. I was doing it wrong. A user control lives in the context of the page where it's rendered so there's no need to set a DataSource on it. In the .ascx file you can just use:
Text = '<%# Bind("MyProperty") %>'
or
Text = '<%# Eval("MyProperty") %>'
where MyProperty is some property of the parent control's DataSource.

How to call a code-behind method from aspx page?

I've an object that contains a field called DevList which is defined like this
public List<string> DevList { get; set; }
I also defined a method called DisplayListOfDevelopers that is supposed to concatenate the list of developers and display it as a one string.
This is how I'm calling the method from aspx.
<asp:TemplateField HeaderText = "Developer(s)">
<ItemTemplate>
<asp:Label
ID="_lblDevList"
runat="server"
Text= '<%# DisplayListOfDevelopers(DevList) %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
But, I'm getting this error: The name 'DevList' does not exist in the current context
Am I missing something?
EDIT
_gvStatus = ds;
_gvStatus.DataBind();
Where ds is just a list of objects that contains the DevList for now.
Thanks for helping
Assuming this is how your class looks:
public class MyItem
{
public List<string> DevList { get; set; }
}
And that
ds = List<MyItem>();
Do this:
In your code-behind:
protected string DisplayListOfDevelopers(object _devList)
{
//Cast your dev list into the correct object
}
In your markup:
<asp:TemplateField HeaderText="Developer(s)">
<ItemTemplate>
<asp:Label
ID="_lblDevList"
runat="server"
Text='<%# DisplayListOfDevelopers(Eval("DevList")) %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
Just be sure to make the function in your code-behind is protected or public.

ASP.NET: Bind a value to a custom user control inside a repeater

I have an ASP.NET control that binds data to a repeater. Inside that repeater, I have another custom user control. I want to pass a value to this second control based on the current binding item.
<asp:Repeater runat="server" ID="ProductList">
<ItemTemplate>
<p>Product ID: <%# Eval("ProductID") %></p>
<myControl:MyCoolUserControl runat="server" ProductID='<%# Eval("ProductID") %>' />
</ItemTemplate>
</asp:Repeater>
The repeater item template correctly prints out my Product ID with the Eval statement, but when I do the same thing to pass the Product ID to MyCoolUserControl, it doesn't work (if ProductID on MyCoolUserControl is a Nullable Int32 - I can debug it and it's always null).
Any ideas how I can do this?
I did a small test and I got it working if the ProductID is a string. After I changed it to and int in the usercontrol I got kind of the same problems.
I did a int.Parse in the datasource to the repeater and got it working again.
Check to see that the ProductId that you pass into the repeaters datasource is of type int.
Mytest app.
string[] values = new string[]{ "12", "13" };
MyRepeater.DataSource = from v in values
select new
{
ProdId = int.Parse(v)
};
MyRepeater.DataBind();
<asp:Repeater runat="server" ID="MyRepeater">
<ItemTemplate>
<My:control runat="server" ProductId='<%# Eval("ProdId") %>' />
</ItemTemplate>
</asp:Repeater>
and in the usercontrol:
public int? ProductId
{
set { MyLabel.Text = value.Value.ToString(); }
}

Binding entities with foreign key to datalist

I have the following code:
var devices = from d in ctx.Devices.Include("DeviceGroups")
where d.DeviceEnabled == true
select d;
dlTerminals.DataSource = devices;
On the front end I do the following:
<asp:DataList ID="dlTerminals" runat="server" DataKeyField="DeviceId" GridLines="None" RepeatColumns="2" RepeatDirection="Horizontal" Width="100%">
<ItemTemplate>
<%# Eval("DeviceGroups.GroupName")%>
</ItemTemplate>
</asp:DataList>
But I get the following error:
does not contain a property with the name 'GroupName'.
Found a solution:
select new { d.DeviceId, d.MAC, d.DeviceType, d.LastConnectTime, d.DeviceGroups.FirstOrDefault().GroupName };
As you are developing asp.net flattening the data is probably the best solution. You may also consider adding a property to your class like
public string DeviceGroupName
{
get
{
return this.DeviceGroups.FirstOrDefault();
}
}

Binding Gridview to IList<BusinessObject> that contains an IList<BusinessObject>

I'm having trouble figuring out how to bind a custom IList to a gridview. The IList contains another custom IList. I need to bind a property from this IList to the gridview.
public class Seminar : BusinessObject
{
private string _description = String.Empty;
private List<User> _attendees;
public string Description {get {return _description;} set {_description = value;}}
public List<User> Attendees {get {return _attendees;} set {_attendees = value;}}
}
public class User : BusinessObject
{
private string _name = String.Empty;
public string Name { get { return _name; } set { _name = value; } }
}
Backend page.aspx.cs:
List<Seminar> seminarList = SeminarManager.Get(id);
gridSeminars.DataSource = seminarList;
gridSeminars.DataBind();
Frontend page.aspx:
<asp:GridView ID="gridSeminars" runat="server">
<Columns>
<asp:BoundField DataField="Id" />
<asp:BoundField DataField="Description" />
<asp:BoundField DataField="Name" />
</Columns>
</asp:GridView>
The problem is with populating the "Name" field in the gridview. All suggestions are welcome.
Have you tried,
Attendees.Name
Edit:
Attendees is an IEnumerable itself. The above suggestion only works with Attendee.Name
If you wan´t to display all the attendees you need to make a templatefield and maybe use a repeater or something...something like:
<asp:TemplateField>
<ItemTemplate>
<asp:Repeater runat="server" DataSource='<%# Eval("Attendees") %>'>
<ItemTemplate>
<tr>
<td>
Name
</td>
<td>
<%# Eval("Name")%>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:TemplateField>
Johan's answer is a good one, specifically the part about how you are trying to bind a collection to a column that is expecting something that can be converted to a string.
Another option would be to put a TemplateField that contains the bindable control (Repeater, another GridView, etc.) you choose to use and binding the DataSource property to the Attendees property of your business object.
Also, I don't if you're married to the idea of using a GridView, but in cases like these where you need more control of the layout, I would suggest the new ListView (.NET 3.5) control, or lately I've just been using nested repeaters so I can have more refined control of the layout I am trying to generate.
Hope this helps.
I'm assuming you want to flatten the hierarchy and display one row for every user. If you have access to Linq, you can use this:
List<Seminar> seminarList = SeminarManager.Get(id);
gridSeminars.DataSource = from seminar in seminarList // loop through all of the seminars in the list
from user in seminar.Attendees // loop through all of the users in the current seminar
select new // create a new, flattened object to bind to.
{
seminar.Id,
seminar.Description,
user.Name
};
gridSeminars.DataBind();
http://weblogs.asp.net/zeeshanhirani/archive/2008/03/26/select-many-operator-part-1.aspx

Resources