ASP.NET using Bind/Eval in .aspx in If statement - c#

in my .aspx I'm looking to add in an If statement based on a value coming from the bind. I have tried the following:
<% if(bool.Parse(Eval("IsLinkable") as string)){ %>
monkeys!!!!!!
(please be aware there will be no monkeys,
this is only for humour purposes)
<%} %>
IsLinkable is a bool coming from the Binder. I get the following error:
InvalidOperationException
Databinding methods such as Eval(), XPath(), and Bind() can only
be used in the context of a databound control.

You need to add your logic to the ItemDataBound event of ListView. In the aspx you cannot have an if-statement in the context of a DataBinder: <%# if() %> doesn't work.
Have a look here: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listview.itemdatabound.aspx
The event will be raised for each item that will be bound to your ListView and therefore the context in the event is related to the item.
Example, see if you can adjust it to your situation:
protected void ListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
Label monkeyLabel = (Label)e.Item.FindControl("monkeyLabel");
bool linkable = (bool)DataBinder.Eval(e.Item.DataItem, "IsLinkable");
if (linkable)
monkeyLabel.Text = "monkeys!!!!!! (please be aware there will be no monkeys, this is only for humour purposes)";
}
}

I'm pretty sure you can do something like the following
(Note I don't have a compiler handy to test the exact syntax)
text = '<%# string.Format("{0}", (bool)Eval("IsLinkable") ? "Monkeys!" : string.Empty) %>'
Yes this is c# and your using vb.net, so you'll need to use vb syntax for a ternary operator.
Edit - was able to throw into into a simple data bind situation, worked like a charm.

You can use asp:PlaceHolder and in Visible can put eval. Like as below
<asp:PlaceHolder ID="plc" runat="server" Visible='<%# Eval("IsLinkable")%>'>
monkeys!!!!!!
(please be aware there will be no monkeys, this is only for humour purposes)
</asp:PlaceHolder>

OMG this took entirely too long to figure out...
<asp:PlaceHolder runat="server" Visible='<%# Eval("formula.type").ToString()=="0" %>'>
Content
</asp:PlaceHolder>
formula.type is a linked table's int column. Thanks for the other contributions to get my resolution.

If you are having issues getting e.Item.DataItem in Bazzz's answer try
protected void ListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
using (ListViewDataItem listViewDataItem = (ListViewDataItem) e.Item)
{
if (listViewDataItem != null)
{
Label monkeyLabel = (Label)e.Item.FindControl("monkeyLabel");
bool linkable = (bool)DataBinder.Eval(listViewDataItem , "IsLinkable");
if (linkable)
monkeyLabel.Text = "monkeys!!!!!! (please be aware there will be no monkeys, this is only for humour purposes)";
}
}
}

I know it is a bit late in the day for this answer but for what it is worth here is my solution to the problem:
<%# (bool)Eval("IsLinkable") ? "monkeys!!!!!!" : "" %>

You can create a method to evaluate the value and return the value you want.
<%# IsLinkableABool( Eval("IsLinkable") ) %>
On the code behind you can create the method as follow
protected String IsLinkableABool(String isLinkable)
{
if (isLinkable == Boolean.TrueString)
{
return "monkeys!!!!!! (please be aware...";
}
else
{
return String.Empty;
}
}

Whenever I've needed to handle conditions within a databound control, I use the OnItemDataBound event.
So you could do:
protected void DataBound_ItemDataBoundEvent() {
bool IsLinkable = (bool)DataBinder.Eval(e.Item.DataItem, "IsLinkable");
if(IsLinkable) {
//do stuff
}
}

We would need to see the rest of your code, but the error message is giving me a bit of a hint. You can ONLY use Eval when you are inside of a data-bound control. SOmething such as a repeater, datagrid, etc.
If you are outside of a data bound control, you could load the value into a variable on the code-behind and make it public. Then you could use it on the ASPX for conditional processing.

For FormView Control refer to this link.
Here is the sample code. My aspx page FormView Control look like below:
<asp:FormView ID="fv" runat="server" Height="16px" Width="832px"
CellPadding="4" ForeColor="#333333" ondatabound="fv_DataBound">
<ItemTemplate>
<table>
<tr>
<td align="left" colspan="2" style="color:Blue;">
<asp:Label ID="lblPYN" runat="server" Text='<%# Eval("PreviousDegreeYN") %>'></asp:Label>
</td>
</tr>
</table>
</ItemTemplate>
</asp:FormView>
I am checking the value for <%# eval("PreviousDegreeYN") %>
If my eval("PreviousDegreeYN") == True, I want to display Yes in my label "lblPYN"
protected void fv_DataBound(object sender, EventArgs e)
{
FormViewRow row = fv.Row;
//Declaring Variable lblPYN
Label lblPYN;
lblPYN = (Label)row.FindControl("lblPYN");
if (lblPYN.Text == "True")
{
lblPYN.ForeColor = Color.Blue;
lblPYN.Text = "Yes";
}
else
{
lblPYN.ForeColor = Color.Blue;
lblPYN.Text = "No";
}
}

Putting condition aspx page is not a good idea.also messy.
U can do using ternary operator.But I suggest u to use rowdatabound events of grid view.
step 1-go to grid view properties.Click on lighting button to list all event.
Step 2-give a name on rowdatabound and double click
protected void onrow(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
TableCell statusCell = e.Row.Cells[8];//Means column 9
if (statusCell.Text == "0")
{
statusCell.Text = "No Doc uploaded";
}
else if (statusCell.Text == "1")
{
statusCell.Text = "Pending";
}
else if (statusCell.Text == "2")
{
statusCell.Text = "Verified";
}
}
}

Related

Dynamically insert non-database value in ItemTemplate for ListView

I have a listview populated from the database. I also have a dynamically calculated value (users inputted postcode relative distance to all database postcode)
I tried adding a label which I can successfully access in the ItemTemplate for the ListView through the ItemDataBound event:
protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
if (CategoryList.SelectedIndex == 5)
{
var lb = e.Item.FindControl("lbPostcodeDistance") as Label;
if (!string.IsNullOrEmpty(tbPostcode.Text))
{
lb.Text = "Distance from: " + tbPostcode.Text;
lb.Visible = true;
}
}
}
}
Above works fine, however, I need to dynamically add an actual value to lb.Text.
The value is calculated in my public IEnumerable<...> ListView1_GetData(), here is a snippet of code:
var inRangeWalks = new List<InRangeWalks>();
foreach (var walk in grabAllWalks)
{
double dis = //calculation here
if (dis <= radius)
{
inRangeWalks.Add(new InRangeWalks(dis, walk));
}
}
inRangeWalks.Sort((x, y) => x.DistanceFromPostcode.CompareTo(y.DistanceFromPostcode));
}
return inRangeWalks.Select(x => x.Walk); //ListView only wants walks, thus returned ordered Walks.
The code above works perfectly, but I need to add the dis value to each item in the ItemTemplate. I've been trying to do it using the ItemDataBound event but I am not sure if this is correct, or even possible.
Here is my ItemTemplate:
<ItemTemplate>
<div class="row">
...
<h6><b>Location:</b> <%# Item.Location%>, <%# Item.Postcode%></h6>
<asp:Label ID="lbPostcodeDistance" runat="server" Text="Label" Visible="false"></asp:Label>
</div>
</ItemTemplate>
How else could I show an additional dynamically calculated value, exactly where the label is in the ItemTemplate?
Ok I actually ended up using Rahul's advice in the comments, and made my ListView use my custom data source.
Was a little bit of a pain to get it up and running but it's now working great!
If someone wants to implement their own data structure, just remember on the ASPX page change the ItemType to the new structure i.e. ItemType="MyProject.Folder.ClassName". And then you can access the property with model binding like: text=<%# Item.MyObject.Property %>

set SkinID Programmatically

I have GridView to display data as Label
<ItemTemplate>
<asp:Label ID="lblIsActive" runat="server" Text='<%# GetIcon((String)Eval("IS_ACTIVE"))%>' SkinID='<%# GetSkinId((String)Eval("IS_ACTIVE"))%>' />
</ItemTemplate>
c#
protected string GetSkinId(string name)
{
if (name == "Y")
{
return "sknActive";
}
else
return "sknInactive";
}
but I get error I can't set SkinID Programmatically, any idea how I can allow SkinID in code behind?
Updated
I decide to not make SkinID, so I'm doing this
<ItemTemplate>
<asp:Label ID="lblIsActive" runat="server" Text='<%# GetIcon((String)Eval("IS_ACTIVE"))%>'
ForeColor='<%# GetColor((String)Eval("IS_ACTIVE"))%>' />
</ItemTemplate>
And my function on c# to get color
protected string GetColor(string name)
{
if (name == "Y")
{
return "#99099";
}
else
return "#03211";
}
I get error that
string can not convert to System.Drawing
The error message is self explanatory. Based on the data source you have the control in your gridview is dynamically getting created and after this it is trying to set the SkinId property and thus the error.
You can achieve this when the row is getting created in your gridview. Yes you can use the RowCreated event of gridvew like this:-
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Label lblIsActive = e.Row.FindControl("lblIsActive") as Label;
if(lblIsActive.Text == "Y")
lblIsActive.SkinID = "sknActive";
else
lblIsActive.SkinID = "sknInactive";
}
}
Please note that this won't work in RowDataBound event since this event is fired after the row is created and when a data row is bound to data.
Update:
First of all your assumption is wrong that we are looping actually we are not. We are simply handling the event which is raised by the gridview control. Anyways since now you have changed your mind and switched to ForeColor approach the problem with your code is that the ForeColor property expects a System.Drawin.Color enum but your passing a string thus the error. For correctint you will have to return Color instead of string like this:-
protected Color GetColor(string name)
{
if (name == "Y")
return Color.Red;
else
return Color.Green;
}
Here I am returning sample colors but you need to replace them with actual intended colors. If you just have the hex string and not sure about the Color enum value then you can use the method mentioned in this answer to do so.
The error message tells you what you need to do: move the initializing of the SkinID property to the Page_PreInit stage of the page lifecycle.
Basically, this entails adding the following event handler to your code behind:
protected void Page_PreInit(object sender, EventArgs e)
{
lblIsActive.SkinId = GetSkinID(IS_ACTIVE); // no need for eval here
}

Checkbox List evaluating all checkmarks as false

I have a simple checkbox list and I'm using a for statement to retrieve the selected values into one string. This has to be simple, but everything is returning false when it evaluates if it is selected.
ASP Code
<asp:CheckBoxList runat="server" ID="ckblInterests" ClientIDMode="Static" RepeatColumns="2" />
ASP.NET Code:
string interests = "";
for (int i = 0; i < ckblInterests.Items.Count; i++)
{
if (ckblInterests.Items[i].Selected)
{
interests += ckblInterests.Items[i].Value + ", ";
}
}
}
The inside if statement evaluates as false each time it loops through. It does count 10 items in the list correctly. I'm stumped at something so simple. Can someone help me identify what might be causing the if statement to return false?
You have code that's dynamically adding the checkboxes to the list on page load (or some other event). This is resulting in the state of those checkboxes being cleared and re-added on each postback. Your page load should probably have an if(!page.ispostback) around that section so that you aren't clearing the content.
With the Following Code (Mostly yours)
Aspx
<div>
<asp:CheckBoxList runat="server" ID="ckblInterests" ClientIDMode="Static" RepeatColumns="2">
<asp:ListItem>Awesome</asp:ListItem>
<asp:ListItem>Tasty</asp:ListItem>
<asp:ListItem>Terrible</asp:ListItem>
</asp:CheckBoxList>
</div>
<asp:Button runat="server" ID="test" OnClick="test_Click" />
<asp:Label runat="server" ID="label"></asp:Label>
c#
protected void test_Click(object sender, EventArgs e)
{
string interests = "";
for (int i = 0; i < ckblInterests.Items.Count; i++)
{
if (ckblInterests.Items[i].Selected)
{
interests += ckblInterests.Items[i].Value + ", ";
}
}
this.label.Text = interests;
}
I was able to produce the following. This is of course after clicking the button.
Are you binding to a datasource that you have not mentioned?
make sure while binding the checkboxlist in page load you have set this check if (!Page.IsPostBack) { ...bind your data }
this should do the trick
I think you need to check the CHECKED property, not SELECTED.

How do I replace a Hyperlink in a Gridview Column with an image, depending on the text in the column?

Question pretty much says it all. On my aspx page I have a GridView and under Columns I have a bunch of BoundFields, one of which is a TemplateField
<asp:TemplateField HeaderText = "Status">
<ItemTemplate>
<asp:HyperLink ID = "HyperLink1" runat = "server" Target = "_blank"
NavigateUrl = '<%# Eval("URL") %>'
Text = '<%#Eval("Status") %>'>
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
Now, I want this Hyperlink to map to a different image, depending on what the text is evaluated to. For example, 'Success' displays a big ol' smiley face instead, 'Failed' displays a frowney face, and so on. How can I achieve this?
Thanks for looking.
You can put an image in the hyperlink like
<img src='/images/status/<%#Eval("Status") %>.jpg' />
and just make a different image for each status by name. Otherwise you'll probably have to do something on the DataBind event.
Try this
protected void myGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
HyperLink HyperLink1 = e.Row.FindControl("HyperLink1");
if(SomeText == "Success")
HyperLink1.NavigateUrl = "Url to Smiley";
else
HyperLink1.NavigateUrl = "Url to Frowney";
}
}
HyperLink HyperLink1 = (HyperLink)e.Row.FindControl("HyperLink1");
switch (HyperLink1.Text)
{
case "Completed":
HyperLink1.ImageUrl = "Images\\Success.png";
HyperLink1.ToolTip = "Completed";
etc
The ToolTip property maps to the alternate text for the image.
Thanks to codingbiz for getting me started.
If you are trying to set the ImageUrl property I suggest using the RowDataBound event. The handler method could would look something like:
protected void questionsGridView_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
DataSourceDataType row;
HyperLink hyperLink1;
if (e.Row.RowType == DataControlRowType.DataRow & e.Row.DataItem is DataSourceDataType)
{
row = (DataSourceDataType)e.Row.DataItem;
hyperLink1 = (HyperLink)e.Row.FindControl("HyperLink1");
hyperLink1.ImageUrl = (row.IsSuccess) ? "~/images/success.png" : "~/images/failure.png";
}
}
Another trick I have used is altering the data object you are binding to to have a property which indicates the URL to use:
partial class DataSourceDataType
{
public string SuccessImgURL
{
get
{
return (IsSuccess) ? "~/images/success.png" : "~/images/failure.png";
}
}
}
Then you bind to that property.
Note: IsSuccess would need to be replaced with your own field name or boolean condition.
I often use this with LINQ to SQL objects, so adding properties can be done in a separate file using partial classes. This way you do not have to worry about the LINQ to SQL tools removing your additions.

Add CSS Class through a Repeater

I have a repeater which dynamically generate tab links using Sitecore (sc:Link) like this:
<asp:Repeater ID="rptTab" runat="server" OnItemDataBound="rptTab_ItemBound">
<ItemTemplate>
<li id= "liTabTest" runat = "server" class="tab-label">
<asp:HyperLink onclick = "javascript: TabClick(this)" runat="server" id="aLink">
<sc:Link ID="hlTabLink" Field="scTabLink" runat="server" ></sc:Link>
</asp:HyperLink>
</li>
</ItemTemplate>
</asp:Repeater>
I manipulate the CSS via JS:
var loadURL;
$(document).ready(function () {
init();
});
function init() {
$("ul#Tab-labels li:first").addClass("TabbedPanelsTabSelected");
};
function TabClick(obj) {
$("ul#Tab-labels li").removeClass("TabbedPanelsTabSelected");
$(obj).addClass("TabbedPanelsTabSelected");
};
Unfortunately, this is not working because each tab is a separate .ASPX page, so the page is getting rendered again and that is why Init() in JS is getting called and CSS is getting executed to the first item everytime.
This is my code behind:
protected void rptTab_ItemBound(Object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Item i = e.Item.DataItem as Item;
Link hlTabLink = e.Item.FindControl("hlTabLink") as Link;
hlTabLink.DataSource = i.Paths.FullPath;
hlTabLink.Field = "Title";
HyperLink aLink = e.Item.FindControl("aLink") as HyperLink;
aLink.NavigateUrl = Sitecore.Links.LinkManager.GetItemUrl(i);
}
}
I tried adding CSS through code-behind but it didnt work because I cannot get the index of the tab (which tab is getting selected). Any solution will be appreciated! Thanks!
Don't run javascript for a task that is better (and easier) accomplished in code-behind. Just set the active class for the repeater item where Sitecore.Context.Item matches the name of the tab. Pseudo code inside ItemDataBound:
if(i == Sitecore.Context.Item)
{
HtmlGenericControl li = e.Item.FindControl("liTabTest");
li.Attributes.Add("class","TabPanelTabbedSelected");
}
Not sure if HtmlGenericControl is correct here, or if it has a CssClass property, but I hope you get the idea. If there is no direct representation for li on the server side, you can also bind a string literal or use a Literal control.
The answer to my question is: The repeater is like an array. So I can get the 1st and Last element of a repeater like this:
string currClass = hc.Attributes["class"].ToString();
string count = e.Item.Controls.Count.ToString();
if (e.Item.ItemIndex == 0)
{
currClass += " TabbedPanelsTabSelected";
}
else if (e.Item.ItemIndex.ToString() == count)
{
currClass += " last";
}
In this way I can add a css to my first element and the last element through Repeater.

Categories