Binding entities with foreign key to datalist - asp.net

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();
}
}

Related

asp.net Gridview ImageField alternate Image

I have below gridview with an imagefield linked with the UserID number.
How can I do if the picture dosnt exist in the specifield older to get an standard alternate picture?
<ItemTemplate>
<asp:Image ID="MainPic" runat="server"
ImageUrl='<%# GetImageUrl(Eval("PerfilId") as string)%>' />
</ItemTemplate>
..
protected string GetImageUrl(string dbImgURL)
{
if (File.Exists(dbImgURL))
{
return dbImgURL;
}
else
{
return "AdminFotoUser/UserPics/BGP1.png";
}
}
Well you can check the image path in onRowDataBound event of the GridView and change it to a common image if file doesn't exist.
using System.IO;
if (File.Exists(path))
{
Console.WriteLine("file exists");
}
else
//Find Control and Bind it to a common image
OR
You could have re-worked your grid a different way:
- instead of using an Image Field column, you could have used a template column like this:
Code:
<asp:TemplateField>
<ItemTemplate>
<asp:Image runat="server" ID="myImg"
ImageUrl='<%# GetImageUrl(Eval(col2) as string) %>' />
</ItemTemplate>
</asp:TemplateField>
Then in your code behind, you have create a function to return the correct image url:
Code:
Updated Ans
//Send Image name from database (DataGrid) as dbImgURL
protected string GetImageUrl(string dbImgURL)
{
if (File.Exists(dbImgURL))
{
return dbImgURL;
}
else
{
return "Green.gif";
}
}

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

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.

ASP.NET Binding integer to CheckBox's Checked field

I have a following ListView item template, in which I am trying to bind integer value to Checked property of CheckBox.
IsUploaded value contains only 0 and 1...
<asp:ListView ID="trustListView" runat="server">
<ItemTemplate>
<asp:CheckBox ID="isUploadedCheckBox" runat="server"
Checked='<%# Bind("IsUploaded") %>' />
</ItemTemplate>
</asp:ListView>
But ASP.NET complains that
Exception Details: System.InvalidCastException: Sepcified cast is not valid
Even though following code using DataBinder.Eval() works,
I need to have a 2-way binding, thus need to use Bind().
<asp:CheckBox ID="isUploadedCheckBox2" runat="server"
Checked='<%# Convert.ToBoolean(
DataBinder.Eval(Container.DataItem, "IsUploaded"))) %>' />
How can I convert 0's and 1's to boolean using Bind()?
[ANSWER]
I have extended auto-generated type through partial class by adding a new property mentioned in the answer by Justin
If you're willing to change the class, add a property on the class that's a boolean
public bool IsUploadedBoolean
{
get { return IsUploaded != 0; }
set { IsUploaded = value ? 1 : 0; }
}
If not, you may have success with a TypeConverter:
Create a custom TypeConverter which will handle 0 and 1 to boolean conversions
Stick the TypeConverterAttribute on the IsUploaded property to direct .NET to your custom typeconverter.
How about adding a property to your class which does the conversion?
public bool IsUploadedBool
{
get { return IsUploaded == 1; }
}
and then bind to this IsUploadedBool property instead of directly to the underlying INT.
Marc
Kind of a cheesy work around would be to use a drop down list with list items to give the same effect:
<asp:DropDownList ID="ddlBool" runat="server" SelectedValue= '<%# Bind("IsUploaded") %>'>
<asp:ListItem Text="True" Value="1" />
<asp:ListItem Text="False" Value="0" />
</asp:DropDownList>
For more information visit:
http://dhondiyals.wordpress.com/2010/05/03/binding-checkbox-with-integer-value-in-gridviewtrick/
How about (btw i am using a stored procedure)
Aspx page
<asp:CheckBox ID="social_facebook" runat="server" Checked='<%# Bind("True") %>' />Facebook
Code behind
cmd.Parameters.Add("#p_facebook", SqlDbType.Bit).Value = social_facebook.Checked;
Solution:
Hi, I'm also using Ajax rating inside a GridView and I ran into this problem. After looking through several forums, I tried this and it worked for me. I hope it helps you:
<%# Convert.ToInt32(Eval("EVALUATION")) %>
returns an integer, since you're using Checked which is an integer.

ASP.NET GridView ItemTemplate

OK I have a GridView and there is a column that I want to be a link if a file exists, otherwise I just want it to be a label. Right now I am changing the controls on RowDataBound event handler using the Row passed in the args. I am not a big fan of this as I am hard coding the column ID, and if it ever changes I will need to remember to change this code. I was hoping I could do a conditional in the asp code to add a link if a property value is not null otherwise add a label. Is this possible? Any different solutions?
I would like something like this:
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<%# if (Eval("LogFileName") == null)
<%#{
<asp:LinkButton ID="LogFileLink" runat="server" CommandArgument='<% #Eval("LogFileName") %>' CommandName="DownloadLogFile" Text='<%# Blah.NDQA.Core.Utilities.GetEnumerationDescription(typeof(Blah.NDQA.Core.BatchStatus), Eval("Status")) %>'>
<%# }
<%# else
<%#{
<asp:Label ID="LogFileLabel" runat="server"Text='<%# Blah.NDQA.Core.Utilities.GetEnumerationDescription(typeof(Blah.NDQA.Core.BatchStatus), Eval("Status")) %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
You can continue to use RowDataBound event but in your aspx you add:
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
In your C# code something like that:
if (LogFileName) {
LinkButton ctrl = new LinkButton();
ctrl.CommandArgument= ...;
ctrl.CommandName= ...;
} else {
Label ctrl = new Label();
ctrl.Text= ...;
}
// You have to find the PlaceHolder1
PlaceHolder1.Controls.Add(ctrl);
In this way you don't have to hard coding the column ID
I know this is a little old now but just in case someone else stumbles across this as I did when looking for an answer to a similar question, I found you can do something like this:
<ItemTemplate>
<asp:ImageButton ID="btnDownload" runat="server"
CommandName="Download"
CommandArgument='<%# Eval("Document_ID") & "," & Eval("Document_Name") %>'
ImageUrl="download.png" ToolTip='<%#"Download " & Eval("Document_Name") %>'
Visible='<%# Not(Eval("Document_ID") = -1) %>' />
</ItemTemplate>
i.e. set the Visible property to evaluate a boolean expression based on your field. If you wanted to display something instead of the download link or button, such as a "Not available" label, then you would just set its Visible property to the opposite boolean expression to your download link. (This is VB.NET not C#, but you get the idea.)
If you're going to be doing this a lot, I suggest writing your own field. The simplest approach is probably to make a NullableHyperlinkField inheriting from HyperlinkField, and render out a plain string if the anchor's URL would otherwise be null.
Use properties on the page to determine if you want to show the label or the link
<asp:GridView ID="gv" runat="server">
<Columns>
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<asp:LinkButton runat="server" Visible='<%# ShowLink %>' PostBackUrl="~/Aliases.aspx" >This is the link</asp:LinkButton>
<asp:Label runat="server" Visible='<%# ShowLabel %>'>Aliases label</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The add the properties ShowLink and ShowLable toyour code behind
public bool ShowLabel
{
get
{
//determine if the label should be shown
return false;
}
private set
{
//do nothing
}
}
public bool ShowLink
{
get
{
//determine if the link should be shown
return true;
}
private set
{
//do nothing
}
}

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