Long time no posts but I’m posting again should have some DDv2 and ASP.Net 4.0 samples soon
I just had need of a conditional UIHint for a project I was working and so here it is.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class ConditionalUIHintAttribute : Attribute { public String UIHint { get; set; } public PageTemplate PageTemplates { get; private set; } public ConditionalUIHintAttribute() { } public ConditionalUIHintAttribute(String uiHint, PageTemplate pageTemplates) { UIHint = uiHint; PageTemplates = pageTemplates; } }
Listing 1 – the conditional UIHint attribute
We will need and IAutoColumnGenerator to generate the columns for us and here that is in Listing 2 I’ve simplified it and all the extra code extension methods are in the sample at the end of the article.
/// <summary> /// Implements the IAutoFieldGenerator interface and /// supports advanced scenarios such as declarative /// column ordering, workaround for attribute /// localization issues. /// </summary> public class AdvancedFieldGenerator : IAutoFieldGenerator { private MetaTable _table; private bool _multiItemMode; protected Page _page; /// <summary> /// Creates a new AdvancedFieldGenerator. /// </summary> /// <param name="table">The table this class generates fields for.</param> /// <param name="multiItemMode"><value>true</value> to indicate a /// multi-item control such as GridView, <value>false</value> for /// a single-item control such as DetailsView. /// </param> public AdvancedFieldGenerator(MetaTable table, bool multiItemMode, Page page) { if (table == null) throw new ArgumentNullException("table"); _table = table; _multiItemMode = multiItemMode; _page = page; } public ICollection GenerateFields(Control control) { var template = _page.GetPageTemplate(); var fields = from c in _table.GetVisibleColumns(_multiItemMode, template) select new DynamicField() { DataField = c.Name, HeaderText = c.DisplayName, UIHint = c.ConditionalUIHint(template) }; return fields.ToList(); } }
Listing 2 – IAutoColumnGenerator
The neat thing here is the ConditionalUIHint extension method that returns the ConditionalUIHint (see it in Listing 5) if the PageTemplate matches otherwise the standard UIHint is returned, here I’ve created a different Boolean field template called AltBoolean that is used only in Edit pages; you could also specify:
[ConditionalUIHint("AltBoolean", PageTemplate.Edit | PageTemplate.Insert)]
which would use the condition field template in both Edit and Insert mode, but in the sample metadata you will get a different field template for Edit and Insert pages to show off the feature.
[MetadataType(typeof(ProductMetadata))] partial class Product { partial class ProductMetadata { public Object ProductID { get; set; } public Object ProductName { get; set; } public Object SupplierID { get; set; } public Object CategoryID { get; set; } public Object QuantityPerUnit { get; set; } public Object UnitPrice { get; set; } public Object UnitsInStock { get; set; } public Object UnitsOnOrder { get; set; } public Object ReorderLevel { get; set; } [ConditionalUIHint("AltBoolean", PageTemplate.Edit)] public Object Discontinued { get; set; } // Entity Set public Object Order_Details { get; set; } // Entity Ref public Object Category { get; set; } // Entity Ref public Object Supplier { get; set; } } }
Listing 4 – sample metadata
To use this in a page you would need to:
public partial class Details : System.Web.UI.Page { protected MetaTable table; protected void Page_Init(object sender, EventArgs e) { DynamicDataManager1.RegisterControl(DetailsView1); table = DetailsDataSource.GetTable(); DetailsView1.RowsGenerator = new AdvancedFieldGenerator(table, true, this); }
Listing 3 – Page_Init Details page
move the table assignment to the Page_Init and add the
DetailsView1.RowGenerator = new AdvancedFieldGenerator(table, true, Page);
to the Page_Init of each page you want to use it with. I’ve added this to every page in the sample.
Below are the extension methods attributes required to use the above code
/// <summary> /// Conditionals the UI hint. /// </summary> /// <param name="column">The column.</param> /// <param name="currentPage">The current page.</param> /// <returns></returns> public static String ConditionalUIHint(this MetaColumn column, PageTemplate currentPage) { var conditionalUIHint = column.GetAttribute<ConditionalUIHintAttribute>(); if (conditionalUIHint != null && conditionalUIHint.AlternateUIHint(currentPage)) return conditionalUIHint.UIHint; else return column.UIHint; } /// <summary> /// Alternates the UI hint. /// </summary> /// <param name="cUIHint">The c UI hint.</param> /// <param name="currentPage">The current page.</param> /// <returns></returns> public static Boolean AlternateUIHint(this ConditionalUIHintAttribute cUIHint, PageTemplate currentPage) { return (cUIHint.PageTemplates & currentPage) == currentPage; }
Listing 5 – Extension methods
Download
All other extension methods are provided in the sample.
Have fun
For the next post I think we may be able to use a FieldTemplateFatory like the EnumFieldTemplateFactory from the old Futures sample. And maybe something extra for ASP.Net 4.0 using the MetaModel classes