Using XPath With Conditional Statement Inside Repeater - asp.net

I am trying to add a conditional statement to my repeater, but I am receiving the following error:
Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
The code I am trying to use is as follows:
<asp:Repeater ID="repLeftmenu" DataSourceID="xmlMenu" runat="server" EnableViewState="false">
<HeaderTemplate>
<ul class="leftMenu">
</HeaderTemplate>
<ItemTemplate>
<li>
<% If XPath("#url").ToString = HttpContext.Current.Request.Url.AbsolutePath.ToString Then%>
<a href="<%# XPath("#url") %>">
<%# XPath("#title")%>
</a>
<% Else %>
<a href="<%# XPath("#url") %>">
<%# XPath("#title")%>
</a>
<% End If%>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
Is there something wrong with my syntax?
Thanks,
crjunk

You are using databinding expresions in regular code blocks, which is not supported. Databinding expressions should appear inside <%# ... %> blocks. Regular code blocks look like this: <% ... %>. (The only difference is the # at the beginning of the block.)
If you need a conditional inside a databinding block, you need to use an expression (simply said: a one-liner). The only way to accomplish this is by using the following code:
<%# If(XPath("Url").ToString = HttpContext.Current.Request.Url.AbsolutePath.ToString, "Display this when true", "Display this when false") %>
This can quickly become unwieldy when whole blocks of HTML are conditionally displayed. What you could do then is to create both blocks and set the visibility of each based on the conditional expression:
<span runat="server" visible='<%# XPath("Url").ToString = <%# If(XPath("Url").ToString = HttpContext.Current.Request.Url.AbsolutePath.ToString %>'>
HTML that should be displayed when condition is true
</span>
<span runat="server" visible='<%# XPath("Url").ToString <> <%# If(XPath("Url").ToString = HttpContext.Current.Request.Url.AbsolutePath.ToString %>'>
HTML that should be displayed when condition is false
</span>

Related

Inline Widgets in Kentico Repeater

I have a repeater that evaluates the content field from a page. This content may have inline widgets in it:
Now, normally I would wrap Eval("Content") in a placeholder with EnableViewState="false" and then resolve it dynamically in code behind but the problem is that the repeater repeats the ID for the placeholder rendering it invalid.
Is there anyway around this?
<cms:CMSUniView ID="MainNavMenu" runat="server" >
<HeaderTemplate>
<ul>
<li>
</HeaderTemplate>
<ItemTemplate>
<a href="<%# Eval("Link") %>"
title="<%# HTMLHelper.HTMLEncode( Convert.ToString(Eval("DocumentName"))) %>" >
<%# HTMLHelper.HTMLEncode( Convert.ToString(Eval("DocumentName"))) %>
</a>
<%# Eval("Content") %>
</ItemTemplate>
<SeparatorTemplate>
</li>
<li>
</SeparatorTemplate>
<FooterTemplate>
</li>
</ul>
</FooterTemplate>
</cms:CMSUniView>
You can try to resolve the content by using CMS.MacroEngine.MacroResolver.Resolve() method. So your code will look like:
<%# MacroResolver.Resolve(Eval("Content").ToString()) %>
And if you want to find any control inside a repeater template, I guess you should do it on ItemDataBound event. Example

How to make this data control reusable for different content and data?

I'm using ASP.NET Web Forms, and I've got a Repeater control to display some data. Currently it looks like this:
<asp:Repeater runat="server" ID="blah" OnItemDataBound="blah" OnItemCommand="blah">
<HeaderTemplate>
<ul class="itemList">
</HeaderTemplate>
<ItemTemplate>
<li runat="server" id="listItem" class="itemNormal" onmouseover="this.className = 'itemHover';" onmouseout="this.className = 'itemNormal';">
<asp:LinkButton runat="server" ID="btn_select" CommandName="Select" Text="Select" style="display: none;"></asp:LinkButton>
<strong>Date/Time:</strong> <%# DataBinder.Eval(Container.DataItem, "date") %><br />
<strong>Details:</strong> <%# DataBinder.Eval(Container.DataItem, "details") %><br />
<strong>Status:</strong> <%# DataBinder.Eval(Container.DataItem, "status") %><br />
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
This list has hover behaviour, etc. and I'd like to reuse the same style of list across my project, just with different data (really just replacing the three lines with <strong> tags in). However, I obviously don't want to copypaste and change it every time it's used, so I thought I'd try and make it into a User Control:
<asp:Repeater runat="server" ID="blah" OnItemDataBound="blah" OnItemCommand="blah">
<HeaderTemplate>
<ul class="itemList">
</HeaderTemplate>
<ItemTemplate>
<li runat="server" id="listItem" class="itemNormal" onmouseover="this.className = 'itemHover';" onmouseout="this.className = 'itemNormal';">
<asp:LinkButton runat="server" ID="btn_select" CommandName="Select" Text="Select" style="display: none;"></asp:LinkButton>
<%= DataString %>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
And in my corresponding class in CodeBehind:
public string DataString { get; set; }
So my main aim was to do this:
<uc:MyUserControl runat="server" ID="blah" DataString="<strong>Date/Time:</strong><%# DataBinder.Eval(Container.DataItem, "date") %> ETC..." />
But it seemed that ASP.NET wanted to evaluate the <% %> in the string there and then, and I tried different ways to get around it such as this:
<% string theDataString = "<strong>Date/Time:</strong> <%# DataBinder.Eval(Container.DataItem, "date") %>"; %>
<uc:MyUserControl runat="server" ID="blah" DataString='<%= theDataString %>' />
But I ran into trouble again with the closing %> in theDataString, and even after replacing it with something like {0: %} (to escape the % sign: can't remember the exact syntax), which did escape it correctly, I discovered that you can't actually use the <%= %> inside an attribute, which was annoying.
My last-ditch attempt was to set DataString in my page's CodeBehind, and the HTML <strong> rendered correctly, but ASP.NET didn't evaluate the <%# %> and just spat it out literally. So I'm kind of stuck as I can't think of anything else... (by the way I'm still relatively new to ASP.NET)
I'm not even sure this is a good way to go about it - previously I thought about making it into a templated user control but this method seemed simpler and it was something I already knew how to do, or so I thought. So any help with this would be greatly appreciated, thanks!
EDIT: Just to be clear, my emphasis here is on the re-usability of this particular control - so I will be able to display different types of data records in this style of list (clickable, highlight behaviour etc).
If your goal is to have three lines appear as bold instead of normal text, then your best bet is to use something more geared towards website-display than something programmatic and heavy-handed like a dynamic server-side user control. For example:
<asp:Repeater runat="server" ID="blah" OnItemDataBound="blah" OnItemCommand="blah">
<HeaderTemplate>
<ul class="itemList">
</HeaderTemplate>
<ItemTemplate>
<li runat="server" id="listItem" class="itemNormal" onmouseover="this.className = 'itemHover';" onmouseout="this.className = 'itemNormal';">
<asp:LinkButton runat="server" ID="btn_select" CommandName="Select" Text="Select" style="display: none;"></asp:LinkButton>
<span class="displayMode">Date/Time:</span> <%# DataBinder.Eval(Container.DataItem, "date") %><br />
<span class="displayMode">Details:</span> <%# DataBinder.Eval(Container.DataItem, "details") %><br />
<span class="displayMode">Status:</span> <%# DataBinder.Eval(Container.DataItem, "status") %><br />
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
And then, programmtically show:
<style type="text/css">
.displayMode { font-weight: bold; }
/* and/or */
.displayMode { text-decoration: underline; }
</style>
Use the right tool for the job, in this case, I don't feel as though server-side code is the right way to accomplish this task. If, on the other hand, you need to change the content of the insides of your <li> tags, then yes you would have to do it in C#. However, if that were the case you could easily bind it to a different object or use a different control or inherit the control or any number of other methods. For your specific case, just use standard HTML manipulation techniques.

Add div conditionally says The name container does not exist in the current context

I want to add HTML div conditionally in rotator control. I am using the following code but it says "The name container does not exist in the current context" at DataBinder.Eval(Container.DataItem, "COL_ID")
<telerik:RadRotator ID="rtrList" runat="server" Width="830px" Height="100px"
FrameDuration="10" RotatorType="ButtonsOver" ScrollDuration="450" WrapFrames="true"
ItemWidth="100" ItemHeight="80" >
<ItemTemplate>
<asp:HiddenField ID="hdfId" runat="server" Value='<%# Eval("COL_ID") %>' />
<div id="div" runat="server" title='<%# Eval("NAME") %>' class="widget_item">
<span>
<%# Eval("TITLE") %>
</span>
</div>
<%if (Convert.ToInt32(DataBinder.Eval(Container.DataItem, "COL_ID")) % 2 == 0)
{%>
<div></div>
<%} %>
</ItemTemplate>
</telerik:RadRotator>
Please guide me where I am wrong. as I am using DataBinder.Eval & Container.DataItem for the first time.
Regards,
Kash
The error implies that this data item does not exist in the item bound to the control.
For example. If you were binding to a table, the table must have a column called "Col_ID" or this will throw an error.
Can you add your code for binding the control to the data source?
Use this syntax instead of the if:
<%# (Convert.ToInt32(DataBinder.Eval(Container.DataItem, "COL_ID")) % 2 == 0) ? "<div></div>" : "" %>

ASP.NET Using If statement with Container in a list view

In my ListView I want to use a property of the Container in an if statement on the aspx page as shown below. But I'm getting a "The name 'Container' does not exist in the current context" error. Can I not the Container in an if statement?
<ItemTemplate>
<tr>
<td>
<% if (EDIT_INDEX == (((ListViewItem)Container) as ListViewDataItem).DataItemIndex )
{%>
<span id="row<%#(((ListViewItem)Container) as ListViewDataItem).DataItemIndex %>"
Some Stuff
</span>
<% } %>
Container is only available in binding expressions. Use a <%# .. %> block with the ternary operator (?:) and string concatenation to achieve the same thing.
Another solution that I have used is to put stuff in different <asp:Placeholder> controls whose Visible properties are binded to different boolean expressions and put the different possible representations inside those placeholders. Something like:
<ItemTemplate>
<tr>
<td>
<asp:Placeholder runat="server"
Visible='<%# EDIT_INDEX == (((ListViewItem)Container) as ListViewDataItem).DataItemIndex %>'>
<span id='row<%#(((ListViewItem)Container) as ListViewDataItem).DataItemIndex %>'>
Some Stuff
</span>
</asp:Placeholder>

ASP.NET: How to convert <A> or HtmlAnchor to static text?

i have a repeater that will output a series of items:
<asp:repeater ... runat="Server">
<itemtemplate>
<%# GetItemText %>
<itemtemplate>
<asp:repeater>
But some items will not have an associated link, so i don't want them to be clickable. i tried making it a runat=server HtmlAnchor, and set the htmlAnchor.Disabled = true for the items are should not actually have a link - but they can still be clicked (it just makes the text gray)
i know how i'd do it in the olden days:
<% If IsLink Then %>
<A href="<% =GetItemLink%">
<% End If %>
<% =GetItemText %>
<% If IsLink Then %>
</A>
<% End If %>
But that's the messy mixing code and html ASP way. What's the ASP.NET way?
Use an <asp:HyperLink > control, which displays the text normally if no link is supplied.
Edited to include example:
<asp:repeater ... runat="Server">
<itemtemplate>
<asp:HyperLink ... runat="server" NavigateUrl="<%# GetItemLink(...) %>"> <%# GetItemText %></asp:HyperLink>
<itemtemplate>
<asp:repeater>
In the above example, the anchor tag will be rendered to html regardless, but if the NavigateUrl attribute is an empty string, there will be no href at all and every browser I've ever used renders the text in a manner similar to spans (so look out for custom styles on <a >'s).

Resources