Still not sure if I should call the .Net 4.0 v2
For the original article see Conditional UIHint from back in October last year, what we want to achieve is change the Field Template in use by page i.e. lets say we have Foreign Key column which would use the default ForeignKey field template but I wanted to use a custom field template during edit currently I would need to create two custom field templates one for edit and one for read only modes. With the ConditionalUIHint I can just apply the attribute like so:
[ConditionalUIHint("MyForeignKey", PageTemplate.Edit)]
And then in Edit mode it would use my custom field template.
As I said in my previous post on this for DDv1 in .Net 4.0 we can create our own custom Meta Classes (MetaModel, MetaTable and MetaColumn etc.); now I said if we could override the UIHint property of the MetaColumn, MetaChildrenColumnand MetaForeignKeyColumn’s then this sample could be made cooler i.e. to get this in DD all we would have to do is change this
private static MetaModel s_defaultModel = new MetaModel(); public static MetaModel DefaultModel { get { return s_defaultModel; } }
Listing 1 – getting metamodel in Global.asax.cs
to this
// get the custom metamodel private static MetaModel s_defaultModel = new CustomMetaModel(); public static MetaModel DefaultModel { get { return s_defaultModel; } }
Listing 2 – getting custom metamodel in Global.asax.cs
so all we have to do is use our own custom metamodel in place of the default Dynamic Data MetaModel cool and if you read A Great Buried Sample in Dynamic Data Preview 4 – Dynamic Data Futures you can use this to control all sorts of things centrally in Dynamic Data without touching each page.
If you look back to the A Great Buried Sample in Dynamic Data Preview 4 – Dynamic Data Futures article you will see that there were five files that made up the Custom Meta classes:
Image 1 - Meta Classes
Due to low budget on imagination this post they will all be prefixed with Custom
We will look at the three extension methods first. the first extension method replaces my old method of finding out which page template we are in:
/// <summary> /// page extension /// </summary> private const String EXTENSION = ".aspx"; /// <summary> /// Gets the page template from the page. /// </summary> /// <param name="page">The page.</param> /// <returns></returns> public static PageTemplate GetPageTemplate(this Page page) { // get pages path var path = page.AppRelativeVirtualPath; // trim it so we just have the page name var pageName = path.Substring(path.LastIndexOf("/") + 1, path.Length - path.LastIndexOf("/") - EXTENSION.Length - 1); PageTemplate pageTemplate; // extract the page template from the page name if (Enum.TryParse<PageTemplate>(pageName, out pageTemplate)) return pageTemplate; else return PageTemplate.Unknown; }
Listing 3 – GetPageTemplate extension method
here I’m getting the page template by extracting the page name excluding extension and then matching it to my PageTemplate enum Listing 4 and returning PageTemplate.Unkown if no match is found (after all I may be using some PageTemplates other that the default ones).
[Flags] public enum PageTemplate { // standard page templates Details = 0x01, Edit = 0x02, Insert = 0x04, List = 0x08, ListDetails = 0x10, // default if unknown Unknown = 0xff }
Listing 4 – PageTemplate enum
And then we have two more extension methods that are used in each Meta Column type to return the ConditionalUIHint:
/// <summary> /// Gets the Conditional UIHint. /// </summary> /// <param name="column">The column.</param> /// <param name="baseUIHint">The base UIHint.</param> /// <returns>a UIHint string</returns> public static String GetUIHintConditionally(this MetaColumn column, String baseUIHint) { // need to get the current page template var page = (System.Web.UI.Page)System.Web.HttpContext.Current.CurrentHandler; var pageTemplate = page.GetPageTemplate(); var conditionalUIHint = column.GetAttribute<ConditionalUIHintAttribute>(); if (conditionalUIHint != null && conditionalUIHint.HasConditionalUIHint(pageTemplate)) return conditionalUIHint.UIHint; else return baseUIHint; } /// <summary> /// Determines whether [has conditional UI hint] /// [the specified conditional UI hint]. /// </summary> /// <param name="conditionalUIHint">The conditional UI hint.</param> /// <param name="currentPage">The current page.</param> /// <returns> /// <c>true</c> if [has conditional UI hint] /// [the specified conditional UI hint]; otherwise, <c>false</c>. /// </returns> private static Boolean HasConditionalUIHint( this ConditionalUIHintAttribute conditionalUIHint, PageTemplate currentPage) { return (conditionalUIHint.PageTemplates & currentPage) == currentPage; }
Listing 5 – GetUIHintConditionally and HasConditionalUIHint
In Listing 5 we have GetUIHintConditionally and HasConditionalUIHint the first get the UIHint and if the current page template matches one in the ConditionalUIHint the ConditionalUIHint is returned. The HasConditionalUIHint is used to determine if there is a page template match.
public class CustomMetaColumn : MetaColumn { public CustomMetaColumn( MetaTable table, ColumnProvider columnProvider) : base(table, columnProvider) { } protected override void Initialize() { base.Initialize(); } /// <summary> /// Gets the name of the field template /// specified for the data field. /// </summary> /// <value></value> /// <returns> /// The name of the field template /// specified for the data field. /// </returns> public override string UIHint { get { return this.GetUIHintConditionally(base.UIHint); } } }
Listing 6 – CustomMetaColumn (Children and ForeignKey are basically the same)
Now all we need in each Meta Column type is to call the GetUIHintConditionally with the current UIHint and if the conditions are met then the ConditionalUIHint will replace the default one.
Each of the other Meta classes is there just to facilitate this and are very basic overrides of the base classes.
Also my standard Attribute extension methods are in there.
Downloads
Happy coding