I want to create a "Tree" structured menu that is generated by a datasource.
I know how to do that with an asp.net tree view or a gridview.
However recently I have grown to love bootstrap and I just love the bootstrap mantis menu.
However metismenu only seem to work on lists 'li'. Then this became a problem for me as the list I want to generate is not static is dynamic. So I can't really bind the value one by one I need to have some other way of doing this.
Can anyone give me some ideas on how to achieve this in asp.net webforms?
PS: would a repeater work for this scenario?
You could use a repeater or a listview or pretty much anything that gives you control of the output html...
You have not presented a massive amount of information to go on but I suspect that you have at least some data that contains a text value and a URL.
private void BindMenuData()
{
var menuData = DataLayer.GetMenuStructure();
rptMenu.DataSource = menuData;
rptMenu.DataBind();
}
Then in your HTML/ASPX you will have something like
<asp:Repeater id="rptMenu" runat="Server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<a href='<# Eval("URL")>'><# Eval("LinkText")></a>
</li>
</ItemTempate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
If you then needed sub menus you would need to nest another repeater inside the item template and bind to it in the repeater itemDataBinding/Databound (Cant remember which) event.
The sub menus leads to an extra layer of complexity which could quite easily descend into a mess of spaghetti code so take some time to think it through!
Of course the fall back could always be a method which uses a string builder to generate the HTML for the menu and spit it out to literal.... Not the best option in my opinion though!
Related
Guys i have a job to display the list of subscribers as it is given in the image. I would like to know which data control in ASP.NET would be perfect for this scenario. I am just playing with Listview but i would like get inputs from the folks here. Thank You. Faraaz.
Update1: Should i use list of gridviews (nested inside a listview) here? Or can it be done with a single list view?
Obviously, grid-view would give you desired tabular layout (probably with the minimal efforts with Auto Generated Columns).
However, if paging, sorting, editing are note required then I would rather user Repeater control. The main reason being precise control over the mark-up. For example, grid-view does not support elements such as <colgroup> or <thead> (again, these elements may not be needed for your layout). If paging/sorting/editing etc is needed then ListView is better choice.
As far as, showing multiple tables goes, you can use nested controls - for example, repeater/list-view nesting a grid-view.
EDIT:
You are not very clear about the structure of data that you have and also about the exact layout that you want. So here's what I am assuming - you have a single List<Subscriber> containing both root subscribers and their children. And in the layout, you want one table for root subscribers followed by multiple tables - one for each root subscriber's children.
Mark-up will be something like
<asp:Repeater runat="server" ID="Outer" >
<HeaderTemplate>
<%-- Put a grid here for parent -->
<asp:GridView runat="server" ID="Root" DataSource='<%# GetRootSubscribers() %>' >
... column def etc
</asp:GridView>
</HeaderTemplate>
<ItemTemplate>
<!-- Put a grid here for children for current root subsriber -->
<asp:GridView runat="server" ID="Child" DataSource='<%# GetChildSubscribers(Eval("MemberID")) %>' >
... column def etc
</asp:GridView>
</ItemTemplate>
</asp:Repeater>
This will be supported by two code-behind methods such as
protected IEnumerable<Subscriber> GetRootSubscribers()
{
// I am not sure how you decide if a subscriber is a parent or not, I have just
// illustrated a condition where you have a parent id field to indicate the same
return allSubscribers.Where(s => s.ParentID == null);
}
protected IEnumerable<Subscriber> GetChildSubscribers(object memberId)
{
// I am not sure how you decide a child subscriber, I have just
// illustrated a condition where you have a parent id field to indicate the same
return allSubscribers.Where(s => s.ParentID.Equals(memberId));
}
// bind the outer repeater to root list
Outer.DataSource = GetRootSubscribers();
Outer.DataBind();
Hope this will give you some idea about how to proceed.
to me this is a GridView with usual header texts. The first bar above you can make with any other control or pure HTML right before the grid. ListViews are not grids and in my opinion should not be used when the final expected result is closer to a grid
I have a nested repeater set up but the child repeater control is not being recognised in the code behind. It's not even being added to the designer file. I've tried this on an aspx and an ascx page but both gives the same problem.
<asp:Repeater ID="RepeaterParent" runat="server">
<ItemTemplate>
<asp:Repeater ID="RepeaterChild" runat="server">
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
with this on the page the code behind only recognises the RepeaterParent but not RepeaterChild.
Can anyone help me out here?
Many thanks!
Like any other control that is used within a repeater (or template) control, you need to retrieve the control using FindControl.
So, in your item data bind event handler for the parent, you would do:
var childRepeater = RepeaterParent.FindControl("RepeaterChild") as Repeater;
The RepeaterChild will be accessible when you use FindControl("RepeaterChild") on the parent repeater I think. Can't remember the exact syntax.
Also note that the FindControl method will also take the context of the current item of the parent repeater, as the name you specify will repeat. Naming containers do some work in the background to provide unique naming, but it is hard to track sometimes.
Looking for a custom ASP .NET control were the InnerHTML of a DIV is connected to a databas to fetch the content to render the HTML content from the databas inside the DIV.
Is there one out there I have missed or anyone could tell if its possible to make my own DIV component to make it DataBound?
Thanks,
Stefan
You can't databind to a div, but you can databind to something like a Repeater, which is mainly good for showing rows of data (i.e. repeating the same markup for multiple data items).
If you just want to show one field from one row, you're probably better off with something like a literal:
<div>
<asp:Literal id="myLiteral" runat="server" />
</div>
And then in the code behind...
myLiteral.Text = "some string from the database or wherever";
I have a simple site consisting of a root site with 2 child sites.
Now I want the navigation for all 3 sites to be exactly the same and read:
Root Site | Child Site 1 | Child Site 2
With the currently selected site highlighted.
I have been able to nearly do this manually using an asp:repeater control and portalsitemapprovider. The problem is I can either get just the Root Site on the navigation (set ShowStartingNode to True) or just the child sites, I can't get both.
I know you can get both if you use a sharepoint:aspmenu control and set staticdisplaylevels to 2 but I don't like the messy code this control spits out. Basically i want to emulate this controls behaviour wrapped in my own compliant css. Any ideas?
Also as an addition does anyone have any ideas on how I can have it so if subsite1/2 have subsequent subsites/pages, it doesn't matter how many levels deep in the hierarchy a user is navigating, it still highlights the relevant subsite1 or subsite2? My current method compares currentnode with each of the providers nodes to work out which should be highlighted, but this doesn't work once the user has navigated away from the landing page of each subsite.
Thanks!
I think you have to start at the root and render that node in a first repeater and then use the childnodes of the root as a datasource for a second repeater, something like:
<asp:Repeater runat="server" ID="MenuRepeater"
DataSourceID="MainNavigationDataSource">
<HeaderTemplate>
// code here
</HeaderTemplate>
<ItemTemplate>
// code here
<asp:Repeater runat="server" ID="ChildMenuRepeater"
DataSource='<%# ((SiteMapNode)Container.DataItem).ChildNodes %>'>
<HeaderTemplate>
// code here
</HeaderTemplate>
<ItemTemplate>
// code here
</ItemTemplate>
</ItemTemplate>
For your second question, I think (if I understand it correctly) that you could use SiteMapNode.IsDescendantOf() method but I somehow recall that that will not work in SharePoint so I have used this sort of code to check if a node is the "active" node:
string CurrentContextUrl = SPUtility.GetPageUrlPath(HttpContext.Current);
Uri CurrentUri = new Uri(CurrentContextUrl);
bool Active = CurrentUri.LocalPath.Equals(currentNode.Url);
Hope it helps out somehow :-)
I'm coming from a Rails background and doing some work on a ASP.NET project (not ASP MVC). Newbie question: what's the easiest way to make a custom editor for a table of records?
For example: I have a bunch of data rows and want to change the "category" field on each -- maybe a dropdown, maybe a link, maybe the user types it in.
In Rails, I'd iterate over the rows to build a table, and would have a form for each row. The form would have an input box or dropdown, and submit the data to a controller like "/item/edit/15?category=foo" where 15 was the itemID and the new category was "foo".
I'm new to the ASP.NET model and am not sure of the "right" way to do this -- just the simplest way to get back the new data & save it off. Would I make a custom control and append it to each row? Any help appreciated.
You can REALLY cheat nowadays and take a peek at the new Dynamic Data that comes with .NET 3.5 SP1. Scott Guthrie has a blog entry demoing on how quick and easy it'll flow for you here:
http://weblogs.asp.net/scottgu/archive/2007/12/14/new-asp-net-dynamic-data-support.aspx
Without getting THAT cutting edge, I'd use the XSD generator to generate a strongly typed DataSet that coincides with the table in question. This will also generate the TableAdapter you can use to do all your CRUD statements.
From there, bind it to a DataGrid and leverage all the standard templates/events involved with that, such as EditIndex, SelectedIndex, RowEditing, RowUpdated, etc.
I've been doing this since the early 1.0 days of .NET and this kind of functionality has only gotten more and more streamlined with every update of the Framework.
EDIT: I want to give a quick nod to the Matt Berseth blog as well. I've been following a lot of his stuff for a while now and it is great!
There are a few controls that will do this for you, with varying levels of complexity depending on their relative flexibility.
The traditional way to do this would be the DataGrid control, which gives you a table layout. If you want something with more flexibility in appearance, the DataList and ListView controls also have built-in support for editing, inserting or deleting fields as well.
Check out Matt Berseth's blog for some excellent examples of asp.net controls in action.
Thanks for the answers guys. It looks like customizing the DataGrid is the way to go. For any ASP.NET newbies, here's what I'm doing
<asp:DataGrid ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundColumn DataField="RuleID" Visible="False" HeaderText="RuleID"></asp:BoundColumn>
<asp:TemplateColumn HeaderText="Category">
<ItemTemplate>
<!-- in case we want to display an image -->
<asp:Literal ID="litImage" runat="server">
</asp:Literal>
<asp:DropDownList ID="categoryListDropdown" runat="server"></asp:DropDownList>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
This creates a datagrid. We can then bind it to a data source (DataTable in my case) and use things like
foreach (DataGridItem item in this.GridView1.Items)
{
DropDownList categoryListDropdown = ((DropDownList)item.FindControl("categoryListDropdown"));
categoryListDropdown.Items.AddRange(listItems.ToArray());
}
to populate the intial dropdown in the data grid. You can also access item.Cells[0].text to get the RuleID in this case.
Notes for myself: The ASP.NET model does everything in the codebehind file. At a high level you can always iterate through GridView1.Items to get each row, and item.findControl("ControlID") to query the value stored at each item, such as after pressing an "Update" button.