show second level of sitemap in site navigation - c#

I have a sitemap like this :
<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
<siteMapNode title="Home" >
<siteMapNode title="Services" >
<siteMapNode title="Training" url="~/Training.aspx"/>
</siteMapNode>
</siteMapNode>
</siteMap>
now I wanna to show second level of sitemap in separate division.
<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false" />
<asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource1">
<asp:HyperLink ID="menu_items" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
</asp:Repeater>
<div class="separator"></div>
//Here must child Node(s) displayed
//e.g. return Training

To display the children for the Basic Reporting, Filtering Reports, and Customized Formatting SiteMapNodes, we can add another Repeater to the initial Repeater's ItemTemplate. This second Repeater will be bound to the SiteMapNode instance's ChildNodes property, like so:
<asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource1">
<ItemTemplate>
<li>
<asp:HyperLink runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
<asp:Repeater runat="server" DataSource='<%# ((SiteMapNode) Container.DataItem).ChildNodes %>'>
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
</asp:Repeater>
These two Repeaters result in the following markup (some markup has been removed for brevity):
<li>
Basic Reporting
<ul>
<li>
Simple Display
</li>
<li>
Declarative Parameters
</li>
<li>
Setting Parameter Values
</li>
</ul>
</li>
<li>
Filtering Reports
...
</li>
<li>
Customized Formatting
...
</li>
taken from: http://msdn.microsoft.com/en-us/library/aa581781.aspx

You need to specify the starting node in a new SiteMapDataSource, even though I'm not sure, if it's the best approach. I believe it would be a better idea to read all the nodes in code-behind at once, and then use this source to populate the actual page with the data you want where you want it.
The reason for this is that I'm not a huge fan of a mixing the logic (binding some data source to elements certainly is a logical part) with the presentation (html, etc.). Yes, it would be easy just to spam the aspx file with datasources, but I'm not convinced about it being the best approach.

Related

Rendering dinamically GenericHtmlControl/Literal merged with an Asp.net Control

My Environment is: ASP.NET 4.62 / C# / Boostrap 4 framework
My application renders bootstrap 4 menu from database query.
I've a div in aspx page
<div id="myNav" runat="server"></div>
and i add code behind as
myNav.InnerHtml = mystr.ToString()
Now i need to integrate in the menu a LoginView asp.net control.
Obviously if i add
<asp:LoginView id="LoginView1" runat="server" ViewStateMode="Disabled">
as string, the browser will receive a string a not renders a control ASP.NET.
I need to render something like this
....previous items menu
<asp:LoginView id="LoginView1" runat="server" ViewStateMode="Disabled">
<AnonymousTemplate>
<ul class='nav navbar-nav ml-auto'>
<li class='nav-item'>
<a class='nav-link' href='../../Account/Login.aspx'><span class='fas fa-user'>
</span>Login</a> </li>
<li class='nav-item'><a class='nav-link' href='~/Account/Login.aspx'>
<span class='fas fa-sign-in-alt'></span> Login</a> </li> </ul>
</AnonymousTemplate>
<LoggedInTemplate>
<ul class='nav navbar-nav ml-auto'>
<li class='nav-item'>
<a class='nav-link' href='~/Account/Login.aspx'><span class='fas fa-user'></span></a>
</li>
<li class='nav-item'>
<span class="myText">Hallo, </span><a runat="server" class="username"
href="~/Account/Manage.aspx" title="Profile">
<asp:LoginName runat="server" CssClass="username" />
</a>!
<asp:LoginStatus runat="server" LogoutAction="Redirect" LogoutText="Exit"
LogoutPageUrl="~/Logout.aspx" />
</li> </ul>
</LoggedInTemplate>
</asp:LoginView>
...closing boostrap menu tag
Which is best way to resolve this type of problem ?
I need to change approach ?
You are creating the HTML at the server side; that is a possibility, but as you see, it makes it hard to combine this with ASP.NET server controls.
It would be better to put the HTML on the .aspx-page. I understand that your database knows which menu-items should be visible. And that you want to add 1 additional item, where users can login.
You could use (for example) a GridView with one column.
<Columns>
<asp:TemplateField>
<ItemTemplate>
<div>Your HTML here </div>
<div><%# Item.SomeProperty %></div>
</ItemTemplate>
</asp:TemplateField>
</Columns>
Use the data from your database to render one 'row' per menuitem in the grid. You can customize the TemplateField so it contains the bootstrap-layout as you need it.
It might also be possible to keep your current approach. I think then you should at least not create your opening and closing bootstrap-menu tags in the code-behind. You should put those tags on the .aspx-page itself, the structure would then be:
<opening tag bootstrap menu>
<div id="myNav" runat="server"></div>
<asp:LoginView id="LoginView1" runat="server" ViewStateMode="Disabled"> ... </ ..>
<closing tag bootstrap menu>

Dynamic menu through use of repeater

I am using a repeater to create a menu (Bootstrap styled). I need to initially make the first item active and can't figure out how. This is what I have:
<!-- Nav tabs -->
<ul id="teamTab" class="nav nav-pills pill-marg" role="tablist">
<asp:Repeater runat="server" ID="rptMenu">
<ItemTemplate>
<li role="presentation">
<a class="circular" href='#<%# DataBinder.Eval(Container.DataItem, "GroupAbbrev") %>' aria-controls="home"
role="tab" data-toggle="tab"><%# String.Format("{0}", Eval("GroupName").ToString().ToUpper()) %></a>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
To make the first menu item active, its style has to be "active", like:
<li role="presentation" class="active"><a class="circular" ...>
I think you can just add <%# Container.ItemIndex == 0 ? "active circular" : "circular" %> inside your repeater template (however its been years since I have used WebForms.
Example:
<!-- Nav tabs -->
<ul id="teamTab" class="nav nav-pills pill-marg" role="tablist">
<asp:Repeater runat="server" ID="rptMenu">
<ItemTemplate>
<li role="presentation" class="<%# Container.ItemIndex == 0 ? "active" : "" %>">
<a class="circular" href='#<%# DataBinder.Eval(Container.DataItem, "GroupAbbrev") %>' aria-controls="home"
role="tab" data-toggle="tab"><%# String.Format("{0}", Eval("GroupName").ToString().ToUpper()) %></a>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
Syntax issues aside (if I have any), I know the index is available via ItemIndex, see the docs here.

DataBinding: 'System.Web.SiteMapNode' does not contain a property

I want to add glyphicons to my custom built menu that I built using an <asp:Repeater> and a web.sitemap file as a data source.
Here is what I've tried:
<ul class="nav navbar-nav">
<asp:Repeater runat="server" ID="rptMenu" DataSourceID="smdsMain">
<ItemTemplate>
<li>
<a runat="server" href='<%# Eval("url") %>'>
<span class='glyphicon glyphicon-<%# Eval("glyphicon") %>'></span>
<%# Eval("title") %>
</a>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
<asp:SiteMapDataSource ID="smdsMain" runat="server" ShowStartingNode="false" SiteMapProvider="XmlSiteMapProvider" />
And here's an example of a node in my web.sitemap:
<siteMapNode url="~/Secure/Home/Default" title="Home" description="Home" glyphicon="home" />
Here is the error I get.
System.Web.HttpException: DataBinding: 'System.Web.SiteMapNode' does not contain a property with the name 'glyphicon'.
I everything else works fine without the glyphicon implementation.
I know it is possible to have a custom attribute in your sitemap nodes because someone implemented it in this Stack Overflow post.
So I must be doing something wrong in my customer implementation. What is the correct way to implement this?
After some research I found that you can access custom attributes in this way:
<%# Eval("[attributeName]") %>
Using that knowledge I have implemented into my code like this to get it working:
<ul class="nav navbar-nav">
<asp:Repeater runat="server" ID="rptMenu" DataSourceID="smdsMain">
<ItemTemplate>
<li>
<a runat="server" href='<%# Eval("url") %>'>
<span class='glyphicon glyphicon-<%# Eval("[glyphicon]") %>'></span>
<%# Eval("title") %>
</a>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
<asp:SiteMapDataSource ID="smdsMain" runat="server" ShowStartingNode="false" SiteMapProvider="XmlSiteMapProvider" />

Programmatically use a copy of existing on-page customized control

On one page i use a web-control (do not pay attention that this is not standart webcontrol, there's no difference for that question):
<telerik:RadComboBox runat="server" id="rcbAssocClient" Width="400px"
MarkFirstMatch="true" EnableLoadOnDemand="true"
HighlightTemplatedItems="true"
onitemsrequested="rcbAssocClient_ItemsRequested">
<HeaderTemplate>
<ul>
<li class="col1">FirstName</li>
<li class="col2">LastName</li>
<li class="col3">BirthDate</li>
</ul>
</HeaderTemplate>
<ItemTemplate>
<ul>
<li class="col1">
<%# DataBinder.Eval(Container.DataItem, "FirstName") %></li>
<li class="col2">
<%# DataBinder.Eval(Container.DataItem, "LastName") %></li>
<li class="col3">
<%# DataBinder.Eval(Container.DataItem, "BirthDate", "{0:d/M/yyyy}")%></li>
</ul>
</ItemTemplate>
</telerik:RadComboBox>
How can i save this template to create the same control on another page programmatically like that:
MyRadComboBox cb = new MyRadComboBox();
without rewriting item template and so on.
Thanks in advance for Your time and help.
You can create your template in a separated file ascx and load with method
LoadTemplate
I hope to be helpful

Repeater split after X returned results

I have the following code that outputs a number of list items <li> wrapped within a UL
<asp:Repeater ID="RT_Footer" runat="server">
<HeaderTemplate>
<ul class="ftr-links"></HeaderTemplate>
<ItemTemplate>
<li><asp:HyperLink ID="HL_NAV" runat="server" NavigateUrl='<%# DataBinder.Eval(Container.DataItem, "PageName") %>' Text='<%# DataBinder.Eval(Container.DataItem, "Title") %>'></asp:HyperLink></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
After 7 items are repeated id like to then wrap the next 7 within another UL, is this possible?
Im not a .net developer and Ive been left with the website built by an existing developer.
Any help would be greatly appreciated, thanks
Using ListView is better suited for this than Repeater: It offers to repeat a configurable count of items in a group.
<asp:ListView ID="RT_Footer" runat="server" GroupItemCount="7">
<LayoutTemplate>
<ul runat="server" id="groupPlaceholder" />
</LayoutTemplate>
<GroupTemplate>
<ul class="ftr-links">
<li id="itemPlaceholder" runat="server" />
</ul>
</GroupTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="HL_NAV" runat="server" NavigateUrl='<%# DataBinder.Eval(Container.DataItem, "PageName") %>' Text='<%# DataBinder.Eval(Container.DataItem, "Title") %>' />
</li>
</ItemTemplate>
</asp:ListView>
If you need, you can even throw in a <GroupSeparatorTemplate> to go between your groups.

Categories