Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
After you have developed some skills for making a dynamic data web site; having used some techniques for creating effectively some MetaData files; having made all necessary adjustments to your database model (ERD or O/R or whatever it might be called); having
created a bunch of additional .aspx pages/templates and folders for customizing specific actions for some tables and you already feel like start giving your web site a good and nice user interface:
How can you get to have customized a good set of menus, subemnus and breadcrumbs inside a Dynamic Data ASP.Net web site?
Mr. Naughton has provided techniques for using different templates which obviously are a good starting point to start thinking about using them inside "Menus" but as it had happened to me before, specially with the customization of Foreign Keys in which
I just turned them off (losing a lot of unnecessary time during execution because even tough they might be hidden to the end user eye they are executed in the background) and creating my own set of DropDownLists and GridViews, now I have the problem in not
knowing how to include inside those dynamic pages (templates) controls such as TreeView, etc.
Any idea?
Carlos Porras (El Salvador)
P.S.: I’d like to include that when using my DynamicData web site I have some issues in behaviour that must be resolved:
For instance:
Having chosen as many filter conditions as you may have in your ERD design for creating a record (inserting) the ASP.Net framework wouldn’t allow you to add a second one if not by means of rebuilding the same set you already have before (that means you
MUST choose again from DropDownLists).
That’s pretty ugly! Meaning that Dynamic Data takes you from the "Insert" page to the "List" page and then, when you ask again to insert a new record all previous settings are gone! (kaput)
You said:"Mr. Naughton has provided techniques for using different templates which obviously are a good starting point to start thinking about using them inside "Menus" but as it had happened to me before, specially with the customization
of Foreign Keys in which I just turned them off (losing a lot of unnecessary time during execution because even tough they might be hidden to the end user eye they are executed in the background) and creating my own set of DropDownLists and GridViews, now
I have the problem in not knowing how to include inside those dynamic pages (templates) controls such as TreeView, etc."
Who is Mr. Naughton? Is he a member of ASP.NET?
Please elaborate on your problem of "not knowing how to include inside those dynamic pages (templates) controls such as TreeView, etc." with detailed examples.
Please mark this post as "Answer" and earn a point.
Mr. Naughton owns the C# Bits NotaClue Blog (http://csharpbits.notaclue.net/)
which is considered one of the best blogs in ASP.Net Dynamic Data in the whole community around the world.
What I meant with my question is: how to include those controls (whatever might be required to display a breadcrumb) for putting them inside the a standard Dynamic Page Template such as List, Edit, etc.
Is there a way that you could consider going a little deeper with the firts questions of this thread?
I also have an intersection table of which I'd like to display its names Of the parent tables) instead of its keys. Is there a way of doing this?
You see, I got displayed those labels in the List.aspx page for that specific table (the intersection one).
Those are the same labels I'd like to have displayed in the DropDownLists of its children tables (that are using this intersection table as one of its foreign keys)
Hi Carlos, here's a quick sample of some rough code I have:
First is the Attribute:
/// <summary>
/// Attribute to identify which column to use as a
/// parent column for the child column to depend upon
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class MenuAttribute : Attribute
{
/// <summary>
/// Gets or sets the name of the menu.
/// </summary>
/// <value>The name of the menu.</value>
public String MenuName { get; private set; }
/// <summary>
/// Gets a value indicating whether to show in menu.
/// </summary>
/// <value><c>true</c> if MenuName has been set; otherwise, <c>false</c>.</value>
public Boolean ShowInMenu
{
get { return !String.IsNullOrEmpty(MenuName); }
}
/// <summary>
/// Gets or sets the image path.
/// </summary>
/// <value>The image path.</value>
public String ImagePath { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="MenuAttribute"/> class.
/// </summary>
public MenuAttribute()
{
MenuName = null;
}
/// <summary>
/// Initializes a new instance of the <see cref="MenuAttribute"/> class.
/// </summary>
/// <param name="menuName">Name of the menu.</param>
public MenuAttribute(String menuName)
{
MenuName = menuName;
}
/// <summary>
/// Initializes a new instance of the <see cref="MenuAttribute"/> class.
/// </summary>
/// <param name="menuName">Name of the menu.</param>
public MenuAttribute(String menuName, String imagePath)
{
MenuName = menuName;
ImagePath = imagePath;
}
}
Second is the extension methods for generating the Menu:
public static MenuItemCollection GenerateMenu(this MenuItemCollection root, IEnumerable<MetaTable> accessableTables)
{
var menus = from t in accessableTables
select t;
foreach (var menuName in menus)
{
var menuAttribute = menuName.GetAttribute<MenuAttribute>();
String name = String.Empty;
String imagePath = String.Empty;
if (menuAttribute != null)
{
name = menuAttribute.MenuName;
imagePath = menuAttribute.ImagePath;
}
else
name = menuName.DisplayName;
// create subment
var menu = new MenuItem(name, menuName.Name, imagePath, menuName.ListActionPath);
// add to root
root.Add(menu);
}
return root;
}
public static String GetTable(this RouteCollection routeCollection)
{
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));
if (routeData != null && routeData.Values.ContainsKey("table"))
return routeData.Values["table"].ToString();
return String.Empty;
}
And finaly the page:
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack && Menu1.Items.Count == 0)
{
// filter table by user permission
var menus = from m in MetaModel.Default.VisibleTables.AsEnumerable()
where m.UserAllowedAccess(Page.User)
select m;
//Menu1.Items.Add(new MenuItem("Home", "Home", "~/images/HomeSmall.png", "~/Default.aspx"));
Menu1.Items.Add(new MenuItem("Home", "Home", "", "~/Default.aspx"));
Menu1.Items.GenerateMenu(menus);
var table = RouteTable.Routes.GetTable();
foreach (MenuItem item in Menu1.Items)
{
if (item.Value == table)
item.Selected = true;
}
if (Page.AppRelativeVirtualPath.Contains("Default"))
Menu1.Items[0].Selected = true;
}
}
So in short what I am doing is marking up which table I want in the menu and then usign the extension method I'm populating the menu and finally I'm checking which table I'm on and selecting it in the menu.
You could also create a site map which would do the auto selecting od the current table based on url.
Using the overriding ToString in the orange entity (t66tbl_marcasxlineas) helped a lot. (Down below the ERD is a display of the screen with sample data). By the way, "MARCAS" means "BRANDS" in English.
Which is ok if you were not to have in count that brands (t25) depends on
localtype (m14) too, then I think, it should be necessary to carry on the key value of the localtype (m14) as to display properly the values that could be matched in the
intersection table (t66) as to avoid creating the Cartesian Product of the two tables
(t30) and (t25), because not all "brands" could be matched to a "line" because, as is shown below,
(t25) depends on (m14)
For instance, as an example, "Coca Cola" shouldn't be associated ever to a kind of store "Farmacia" (which is a drugstore
and I undesrstand that it could be possible to sell coca's at a drugstore, but let just assume that in this drugstore it shouldn't happen) because coca should belong to the localtype "Tienda" only (which is a kind of supermarket) .
How can it be customized?. I mean, how can the value could be carried out, like PostBack function for each one of the DropDownLists that could change seeing always that the combination is worth in relation to the (m14) table?
Hi Carlos, I got to thinking over the weekend (I know a dangerous thing) and decided that we should have a control or something to do this for us and so I created the MetaDataSiteMapProvider see my article here SiteMapProvider
for Dynamic Data (.Net 3.5 SP1 and .Net 4.0) and the good news it has sample for .Net 3.51 SP1 and .Net 4.0 [:D]
Dynamic DataSite MapsDynamic Data 4MenusSiteMapProvider
See my blog C# Bits | Twitter @sjnaughton Always seeking an elegant solution.
klca
Member
453 Points
263 Posts
Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
Feb 26, 2010 02:18 PM|LINK
Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
After you have developed some skills for making a dynamic data web site; having used some techniques for creating effectively some MetaData files; having made all necessary adjustments to your database model (ERD or O/R or whatever it might be called); having created a bunch of additional .aspx pages/templates and folders for customizing specific actions for some tables and you already feel like start giving your web site a good and nice user interface:
How can you get to have customized a good set of menus, subemnus and breadcrumbs inside a Dynamic Data ASP.Net web site?
Mr. Naughton has provided techniques for using different templates which obviously are a good starting point to start thinking about using them inside "Menus" but as it had happened to me before, specially with the customization of Foreign Keys in which I just turned them off (losing a lot of unnecessary time during execution because even tough they might be hidden to the end user eye they are executed in the background) and creating my own set of DropDownLists and GridViews, now I have the problem in not knowing how to include inside those dynamic pages (templates) controls such as TreeView, etc.
Any idea?
Carlos Porras (El Salvador)
P.S.: I’d like to include that when using my DynamicData web site I have some issues in behaviour that must be resolved:
For instance:
That’s pretty ugly! Meaning that Dynamic Data takes you from the "Insert" page to the "List" page and then, when you ask again to insert a new record all previous settings are gone! (kaput)
thuhue
All-Star
15625 Points
3146 Posts
Re: Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
Feb 26, 2010 04:23 PM|LINK
You said:"Mr. Naughton has provided techniques for using different templates which obviously are a good starting point to start thinking about using them inside "Menus" but as it had happened to me before, specially with the customization of Foreign Keys in which I just turned them off (losing a lot of unnecessary time during execution because even tough they might be hidden to the end user eye they are executed in the background) and creating my own set of DropDownLists and GridViews, now I have the problem in not knowing how to include inside those dynamic pages (templates) controls such as TreeView, etc."
Who is Mr. Naughton? Is he a member of ASP.NET?
Please elaborate on your problem of "not knowing how to include inside those dynamic pages (templates) controls such as TreeView, etc." with detailed examples.
klca
Member
453 Points
263 Posts
Re: Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
Feb 26, 2010 04:30 PM|LINK
Mr. Naughton owns the C# Bits NotaClue Blog (http://csharpbits.notaclue.net/) which is considered one of the best blogs in ASP.Net Dynamic Data in the whole community around the world.
What I meant with my question is: how to include those controls (whatever might be required to display a breadcrumb) for putting them inside the a standard Dynamic Page Template such as List, Edit, etc.
Carlos Porras (El Salvador)
klca
Member
453 Points
263 Posts
Re: Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
Feb 26, 2010 09:35 PM|LINK
How do you get the framework 4 for VS 2008 ? Is that possible?
Should it be VS2010 only? I don't have a license for VS2010 but for VS2008
Carlos Porras (El Salvador)
sjnaughton
All-Star
25698 Points
5169 Posts
MVP
Re: Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
Feb 26, 2010 11:11 PM|LINK
Hi Carlos, it has trditionaly always been major Framework release with new VS release [:(]
Dynamic Data 4
Always seeking an elegant solution.
klca
Member
453 Points
263 Posts
Re: Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
Feb 26, 2010 11:57 PM|LINK
Mr. Naughton,
Is there a way that you could consider going a little deeper with the firts questions of this thread?
I also have an intersection table of which I'd like to display its names Of the parent tables) instead of its keys. Is there a way of doing this?
You see, I got displayed those labels in the List.aspx page for that specific table (the intersection one).
Those are the same labels I'd like to have displayed in the DropDownLists of its children tables (that are using this intersection table as one of its foreign keys)
Carlos Porras (El Salvador)
sjnaughton
All-Star
25698 Points
5169 Posts
MVP
Re: Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
Feb 27, 2010 12:20 AM|LINK
Hi Carlos, here's a quick sample of some rough code I have:
First is the Attribute:
/// <summary> /// Attribute to identify which column to use as a /// parent column for the child column to depend upon /// </summary> [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class MenuAttribute : Attribute { /// <summary> /// Gets or sets the name of the menu. /// </summary> /// <value>The name of the menu.</value> public String MenuName { get; private set; } /// <summary> /// Gets a value indicating whether to show in menu. /// </summary> /// <value><c>true</c> if MenuName has been set; otherwise, <c>false</c>.</value> public Boolean ShowInMenu { get { return !String.IsNullOrEmpty(MenuName); } } /// <summary> /// Gets or sets the image path. /// </summary> /// <value>The image path.</value> public String ImagePath { get; set; } /// <summary> /// Initializes a new instance of the <see cref="MenuAttribute"/> class. /// </summary> public MenuAttribute() { MenuName = null; } /// <summary> /// Initializes a new instance of the <see cref="MenuAttribute"/> class. /// </summary> /// <param name="menuName">Name of the menu.</param> public MenuAttribute(String menuName) { MenuName = menuName; } /// <summary> /// Initializes a new instance of the <see cref="MenuAttribute"/> class. /// </summary> /// <param name="menuName">Name of the menu.</param> public MenuAttribute(String menuName, String imagePath) { MenuName = menuName; ImagePath = imagePath; } }Second is the extension methods for generating the Menu:
public static MenuItemCollection GenerateMenu(this MenuItemCollection root, IEnumerable<MetaTable> accessableTables) { var menus = from t in accessableTables select t; foreach (var menuName in menus) { var menuAttribute = menuName.GetAttribute<MenuAttribute>(); String name = String.Empty; String imagePath = String.Empty; if (menuAttribute != null) { name = menuAttribute.MenuName; imagePath = menuAttribute.ImagePath; } else name = menuName.DisplayName; // create subment var menu = new MenuItem(name, menuName.Name, imagePath, menuName.ListActionPath); // add to root root.Add(menu); } return root; } public static String GetTable(this RouteCollection routeCollection) { var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current)); if (routeData != null && routeData.Values.ContainsKey("table")) return routeData.Values["table"].ToString(); return String.Empty; }And finaly the page:
protected void Page_Init(object sender, EventArgs e) { if (!IsPostBack && Menu1.Items.Count == 0) { // filter table by user permission var menus = from m in MetaModel.Default.VisibleTables.AsEnumerable() where m.UserAllowedAccess(Page.User) select m; //Menu1.Items.Add(new MenuItem("Home", "Home", "~/images/HomeSmall.png", "~/Default.aspx")); Menu1.Items.Add(new MenuItem("Home", "Home", "", "~/Default.aspx")); Menu1.Items.GenerateMenu(menus); var table = RouteTable.Routes.GetTable(); foreach (MenuItem item in Menu1.Items) { if (item.Value == table) item.Selected = true; } if (Page.AppRelativeVirtualPath.Contains("Default")) Menu1.Items[0].Selected = true; } }So in short what I am doing is marking up which table I want in the menu and then usign the extension method I'm populating the menu and finally I'm checking which table I'm on and selecting it in the menu.
You could also create a site map which would do the auto selecting od the current table based on url.
<?xml version="1.0" encoding="UTF-8"?> <siteMap> <siteMapNode url="" title="root"> <siteMapNode url="default.aspx" title="Home"></siteMapNode> <siteMapNode url="Categories/List.aspx" title="Categories"></siteMapNode> <siteMapNode url="Customers/List.aspx" title="Customers"></siteMapNode> <siteMapNode url="Orders/List.aspx" title="Orders"></siteMapNode> <siteMapNode url="Suppliers/List.aspx" title="Suppliers"></siteMapNode> <siteMapNode url="Products/List.aspx" title="Products"></siteMapNode> </siteMapNode> </siteMap>But of course you would need to manually maintain this.
Dynamic Data Site Maps navigation Menus
Always seeking an elegant solution.
sjnaughton
All-Star
25698 Points
5169 Posts
MVP
Re: Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
Feb 27, 2010 12:27 AM|LINK
Hi Carlos, and the othere things you asked [:)]
I'm also thinking of writing my own SiteMapDataSource
and then it could examin the metadata and return the sitemap data to the control.
I would use ToString() override on you entites as described by Rick Anderson here Improving the FK field display: Showing two fields in Foreign Key columns
Dynamic Data
Always seeking an elegant solution.
klca
Member
453 Points
263 Posts
Re: Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
Feb 27, 2010 03:12 PM|LINK
Hi Mr. Naughton,
Using the overriding ToString in the orange entity (t66tbl_marcasxlineas) helped a lot. (Down below the ERD is a display of the screen with sample data). By the way, "MARCAS" means "BRANDS" in English.
Which is ok if you were not to have in count that brands (t25) depends on localtype (m14) too, then I think, it should be necessary to carry on the key value of the localtype (m14) as to display properly the values that could be matched in the intersection table (t66) as to avoid creating the Cartesian Product of the two tables (t30) and (t25), because not all "brands" could be matched to a "line" because, as is shown below, (t25) depends on (m14)
For instance, as an example, "Coca Cola" shouldn't be associated ever to a kind of store "Farmacia" (which is a drugstore and I undesrstand that it could be possible to sell coca's at a drugstore, but let just assume that in this drugstore it shouldn't happen) because coca should belong to the localtype "Tienda" only (which is a kind of supermarket) .
How can it be customized?. I mean, how can the value could be carried out, like PostBack function for each one of the DropDownLists that could change seeing always that the combination is worth in relation to the (m14) table?
Thanks
Carlos Porras (El Salvador)
sjnaughton
All-Star
25698 Points
5169 Posts
MVP
Re: Customizing Menus and BreadCrumbs inside a Dynamic Data Web Site
Feb 28, 2010 10:35 PM|LINK
Hi Carlos, I got to thinking over the weekend (I know a dangerous thing) and decided that we should have a control or something to do this for us and so I created the MetaDataSiteMapProvider see my article here SiteMapProvider for Dynamic Data (.Net 3.5 SP1 and .Net 4.0) and the good news it has sample for .Net 3.51 SP1 and .Net 4.0 [:D]
Dynamic Data Site Maps Dynamic Data 4 Menus SiteMapProvider
Always seeking an elegant solution.