Monday, June 11, 2012

Dynamic Data Custom Pages: Dynamic/Templated FromView

Continuing on from Part 3 the same techniques will be applied to the FormView, making the FormView Dynamic and also having the facility to dynamically load user defined Templates at runtime.

Fugure 1 – FormViewPage in action

Note the Edit, Delete and New links these all act on this page and do not redirect to other pages.

Altering the Routing

Replace the default route Listing 1

routes.Add(new DynamicDataRoute("{table}/{action}.aspx")

{

    Constraints = new RouteValueDictionary(new { action = "List|Edit|Details|Insert" }),

    Model = model

});

Listing 1 – original routing in Global.asax

With the new routes in Listing 2

routes.Add(new DynamicDataRoute("{table}/{action}.aspx")

{

    Constraints = new RouteValueDictionary(new { action = "List" }),

    Model = model

});

 

routes.Add(new DynamicDataRoute("{table}/{action}/FormViewPage.aspx")

{

    Constraints = new RouteValueDictionary(new { action = "Edit|Details|Insert" }),

    ViewName = "FormViewPage",

    Model = model,

});

Listing 2 – changes to routing in global.asax

Note that the action {table}/{action}/FormViewPage.aspx as a prefix to the page name, this will be used to identify the pages mode (Edit, Delete and Insert)

The FromViewPage

<%@ Page

    Language="C#"

    MasterPageFile="~/Site.master"

    CodeFile="FormViewPage.aspx.cs"

    Inherits="FormViewPage" %>

 

<asp:Content

    ID="Content1"

    ContentPlaceHolderID="ContentPlaceHolder1"

    Runat="Server">

   

    <asp:DynamicDataManager

        ID="DynamicDataManager1"

        runat="server"

        AutoLoadForeignKeys="true" />

 

    <h2><%= table.DisplayName %></h2>

 

    <asp:ScriptManagerProxy

        runat="server"

        ID="ScriptManagerProxy1" />

 

    <asp:UpdatePanel

        ID="UpdatePanel1"

        runat="server">

        <ContentTemplate>

 

            <asp:ValidationSummary

                ID="ValidationSummary_Edit"

                EnableClientScript="true"

                HeaderText="List of validation errors"

                ValidationGroup="FormView_Edit"

                runat="server" />

               

            <asp:ValidationSummary

                ID="ValidationSummary_Insert"

                EnableClientScript="true"

                HeaderText="List of validation errors"

                ValidationGroup="FormView_Insert"

                runat="server" />

                

            <asp:DynamicValidator

                ID="Validator_Edit"

                Display="None"

                ValidationGroup="FormView_Edit"

                ControlToValidate="FormView1"

                runat="server" />

                

            <asp:DynamicValidator

                ID="Validator_Insert"

                Display="None"

                ValidationGroup="FormView_Insert"

                ControlToValidate="FormView1"

                runat="server" />

                

            <asp:FormView

                ID="FormView1"

                DataSourceID="FormViewDataSource"

                OnItemDeleted="FormView_ItemDeleted"

                runat="server" onitemcommand="FormView1_ItemCommand"

                oniteminserted="FormView1_ItemInserted">

            </asp:FormView>

           

            <asp:LinqDataSource

                ID="FormViewDataSource"

                AutoGenerateWhereClause="true"

                EnableDelete="true"

                EnableUpdate="true"

                EnableInsert="true"

                runat="server">

                <WhereParameters>

                    <asp:DynamicQueryStringParameter />

                </WhereParameters>

            </asp:LinqDataSource>

            

            <br />

           

            <div class="bottomhyperlink">

                <asp:HyperLink

                    ID="ListHyperLink"

                    runat="server">Show all items</asp:HyperLink>

            </div>       

       

        </ContentTemplate>

    </asp:UpdatePanel>

</asp:Content>

Listing 3 – FormViewPage.aspx

using System;

using System.IO;

using System.Web.DynamicData;

using System.Web.UI.WebControls;

 

public partial class FormViewPage : System.Web.UI.Page

{

    protected MetaTable table;

 

    protected void Page_Init(object sender, EventArgs e)

    {

        DynamicDataManager1.RegisterControl(FormView1);

        table = FormViewDataSource.GetTable();

 

        // supported templates

        // get tamplate path

        var formViewTemplatePath = table.Model.DynamicDataFolderVirtualPath + "Templates/FormViewPage/" + table.Name + "/";

 

        // load user templates if they exist

        if (File.Exists(Server.MapPath(formViewTemplatePath + "ItemTemplate.ascx")))

            FormView1.ItemTemplate = LoadTemplate(formViewTemplatePath + "ItemTemplate.ascx");

        else

            FormView1.ItemTemplate = new FromViewPageRowGenerator(table, FormViewTemplateType.ItemTemplate);

 

        // load user templates if they exist

        if (File.Exists(Server.MapPath(formViewTemplatePath + "EditItemTemplate.ascx")))

            FormView1.EditItemTemplate = LoadTemplate(formViewTemplatePath + "EditItemTemplate.ascx");

        else

            FormView1.EditItemTemplate = new FromViewPageRowGenerator(table, FormViewTemplateType.EditItemTemplate);

 

        // load user templates if they exist

        if (File.Exists(Server.MapPath(formViewTemplatePath + "InsertItemTemplate.ascx")))

            FormView1.InsertItemTemplate = LoadTemplate(formViewTemplatePath + "InsertItemTemplate.ascx");

        else

            FormView1.InsertItemTemplate = new FromViewPageRowGenerator(table, FormViewTemplateType.InsertItemTemplate);

 

        // load user templates if they exist

        if (File.Exists(Server.MapPath(formViewTemplatePath + "EmptyDataTemplate.ascx")))

            FormView1.EmptyDataTemplate = LoadTemplate(formViewTemplatePath + "EmptyDataTemplate.ascx");

        else

            FormView1.EmptyDataTemplate = new FromViewPageRowGenerator(table, FormViewTemplateType.EmptyDataTemplate);

        //FormView1.FooterTemplate = null;

        //FormView1.HeaderTemplate = null;

        //FormView1.PagerTemplate = null;

    }

 

    protected void Page_Load(object sender, EventArgs e)

    {

        table = FormViewDataSource.GetTable();

        Title = table.DisplayName;

 

        // I don't know if this is

        // the best way to do this

        // get the FormViews mode from the url

        String path = Request.Path.Substring(0, Request.Path.LastIndexOf("/"));

        var qs = path.Substring(path.LastIndexOf("/") + 1, path.Length - (path.LastIndexOf("/") + 1));

        switch (qs)

        {

            case "Details":

                FormView1.DefaultMode = FormViewMode.ReadOnly;

                break;

            case "Edit":

                FormView1.DefaultMode = FormViewMode.Edit;

                break;

            case "Insert":

                FormView1.DefaultMode = FormViewMode.Insert;

                break;

            default:

                break;

        }

        ListHyperLink.NavigateUrl = table.ListActionPath;

    }

 

    protected void FormView_ItemDeleted(object sender, FormViewDeletedEventArgs e)

    {

        if (e.Exception == null || e.ExceptionHandled)

        {

            Response.Redirect(table.ListActionPath);

        }

    }

 

    protected void FormView1_ItemCommand(object sender, FormViewCommandEventArgs e)

    {

        if (e.CommandName == "Cancel")

        {

            // option 1 go back to list

            //Response.Redirect(table.ListActionPath);

 

            // option 2 return to Normal ReadOnly

            FormView1.DefaultMode = FormViewMode.ReadOnly;

        }

    }

 

    protected void FormView1_ItemInserted(object sender, FormViewInsertedEventArgs e)

    {

        // option 1 go back to list

        Response.Redirect(table.ListActionPath);

 

        // option 2 return to Normal ReadOnly

        // note sure how to get this working at the moment

        //Response.Redirect(table.GetActionPath("Details", ???));

    }

}

Listign 4 – FormViewPage.aspx.cs

From Listings 3 and 4 you can see that this is a basic page like Details.aspx but with a FormView. The real magic goes on in the Page_Init event handler where the Templates are either loaded or dynamically generated and also in the Page_Load event handler where the default mode is detected via the URL.

Note: I’m not sure this is the best or most elegant way of doing this, but this will do for now and we will have a look at this again at a later date.

The RowGenerator

This will generate a table based FormView similar to the Details.aspx generated by the wizard (which at the time of writing was still in preview) the dynamically generated layout can be overridden be defining UserControl custom Templates in the ~/DynamicData/Templates/FormViewPage/<TableName>/<templated>.

/// <summary>

/// Template type for the FromViewPageRowGenerator

/// </summary>

public enum FormViewTemplateType

{

    ItemTemplate,

    EditItemTemplate,

    InsertItemTemplate,

    EmptyDataTemplate,

    HeaderTemplate,

    FooterTemplate,

    PagerTemplate,

}

 

/// <summary>

/// Renders templates for ListView

/// </summary>

public class FromViewPageRowGenerator : ITemplate

{

    #region Member Fields, Constructor, Enums & Properties

    private MetaTable _table;

private FormViewTemplateType _type;

 

    public FromViewPageRowGenerator(MetaTable table, FormViewTemplateType type)

    {

        _table = table;

        _type = type;

    }

   

1 comment:

  1. I am really loving the theme/design of your site.
    Do you ever run into any browser compatibility issues?
    A few of my blog readers have complained about my blog
    not operating correctly in Explorer but looks great in Opera.
    Do you have any advice to help fix this problem?


    Here is my web-site cellulite treatment cream

    ReplyDelete