locked
Customize edit page RRS feed

  • Question

  • User-751080518 posted

    Hi!

    I would like to customize Edit Page template.

    Default Edit page makes DropDown control for each Foreign Column.

    I would like to make an image next to drop down. When user would click on that image, the modal grid with data of foreign table would appear.

    Then on select event of grid, the dropdown selected value would change with the one selected in modal (foreign) grid.

     

    I tried to make that with changing the ForeignKey field template, but I have problems with postback.

    I made modal grid with foreign table data, but when I filter, select, or do anything, that fires postback, the modal window closes.

    I tried to fix that with function, that checks which control fired postback, and reshowing the modal window if the control was one of those on modal ...

    After that, modal window showed up for every foreign key in current table.

    So I think the right approach would be to change Edit page template.

    If I put ModalPopupExtender + GridView ... and all other stuff on edit page, how can I than access this controls from field template?

    I hope that someone can help me with this, because it is very hard to select foreign key value fro dropdown if foreign table has 5-10 columns and many rows ...

    It's easier to select from grid -> lookup table.

     

    Here is some of the code I allredy managed to write:

    ForeignKey_Edit.ascx:

    <%@ Control Language="C#" CodeFile="ForeignKey_Edit.ascx.cs" Inherits="ForeignKey_EditField" %>
    <%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolKit" %>
    <%@ Register Src="~/DynamicData/Content/GridViewPager.ascx" TagName="GridViewPager"
        TagPrefix="asp" %>
    <asp:DropDownList ID="DropDownList1" runat="server" CssClass="DDDropDown">
    </asp:DropDownList>
    <asp:ImageButton ID="Image1" runat="server" OnClick="Image1_Click" ImageUrl="~/DynamicData/Content/Images/fk_select.gif" />
    <asp:RequiredFieldValidator runat="server" ID="RequiredFieldValidator1" CssClass="DDControl DDValidator"
        ControlToValidate="DropDownList1" Display="Static" Enabled="false" />
    <asp:DynamicValidator runat="server" ID="DynamicValidator1" CssClass="DDControl DDValidator"
        ControlToValidate="DropDownList1" Display="Static" />
    <asp:UpdatePanel runat="server" ID="updPanel" UpdateMode="Conditional">
        <ContentTemplate>
            <asp:Panel ID="FKLookupTablePanel" runat="server" Style="display: none; background-color: White;">
                <asp:DynamicDataManager ID="DynamicDataManager1" runat="server" AutoLoadForeignKeys="false">
                    <DataControls>
                        <asp:DataControlReference ControlID="FKGridView" />
                    </DataControls>
                </asp:DynamicDataManager>
                <fieldset id="MultiSearchFieldSet" class="DD" runat="server" visible="false">
                    <legend>Full Text Search</legend>
                    <asp:TextBox ID="txbMultiColumnSearch" CssClass="DDTextBox" runat="server" />
                    <asp:Button ID="btnMultiColumnSearchSubmit" CssClass="DDControl" runat="server" Text="Search"
                        OnClick="btnMultiColumnSearch_Click" />
                    <asp:Button ID="btnMultiColumnSearchClear" CssClass="DDControl" runat="server" Text="Clear"
                        OnClick="btnMultiColumnSearch_Click" />
                </fieldset>
                <asp:Button ID="ButtonShowPopup" runat="server" Style="display: none" />
                <ajaxToolKit:ModalPopupExtender ID="FKModalPopupExtender" runat="server" TargetControlID="ButtonShowPopup"
                    PopupControlID="FKLookupTablePanel" OkControlID="LinkButtonSave" CancelControlID="LinkButtonCancel"
                    BackgroundCssClass="modalBackground" />
                <asp:GridView ID="FKGridView" runat="server" DataSourceID="FKGridDataSource" AutoGenerateSelectButton="false"
                    EnablePersistedSelection="true" AllowPaging="True" AllowSorting="True" CssClass="DDGridView"
                    RowStyle-CssClass="td" HeaderStyle-CssClass="th" CellPadding="6">
                    <Columns>
                        <asp:TemplateField>
                            <ItemTemplate>
                                <asp:LinkButton ID="LinkButtonSelect" runat="server" CommandName="Select" Text="Select" />
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                    <SelectedRowStyle CssClass="DDSelected" />
                    <PagerStyle CssClass="DDFooter" />
                    <PagerTemplate>
                        <asp:GridViewPager ID="GridViewPager1" runat="server" />
                    </PagerTemplate>
                    <EmptyDataTemplate>
                        There are currently no items in this table.
                    </EmptyDataTemplate>
                </asp:GridView>
                <asp:LinqDataSource ID="FKGridDataSource" runat="server" EnableDelete="false" EnableUpdate="false" />
                <asp:QueryExtender ID="GridQueryExtender" TargetControlID="FKGridDataSource" runat="server">
                </asp:QueryExtender>
                <asp:LinkButton ID="LinkButtonSave" runat="server" CausesValidation="False">Save</asp:LinkButton>
                <asp:LinkButton ID="LinkButtonCancel" runat="server" CausesValidation="False">Cancel</asp:LinkButton>
            </asp:Panel>
        </ContentTemplate>
    </asp:UpdatePanel>

    ForeignKey_Edit.ascx.cs

    using System;
    using System.Linq;
    using System.Web.DynamicData;
    using System.Web.UI.WebControls;
    using System.Collections.Generic;
    using System.Web.UI;
    using System.Collections.Specialized;
    using System.Web.UI.WebControls.Expressions;
    
    public partial class ForeignKey_EditField : System.Web.DynamicData.FieldTemplateUserControl
    {
    
        private String[] DisplayColumns { get; set; }
    
        protected MetaTable table;
    
        public Boolean EnableDelete { get; set; }
        public Boolean EnableInsert { get; set; }
        public Boolean EnableUpdate { get; set; }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            if (DropDownList1.Items.Count == 0)
            {
                if (Mode == DataBoundControlMode.Insert || !Column.IsRequired)
                {
                    DropDownList1.Items.Add(new ListItem("[Not Set]", ""));
                }
                PopulateListControl(DropDownList1);
            }
    
            SetUpValidator(RequiredFieldValidator1);
            SetUpValidator(DynamicValidator1);
    
            if (Page.IsPostBack)
            {
                string sSourceControl = getPostBackControlName();
                if (sSourceControl == btnMultiColumnSearchSubmit.ID ||
                    sSourceControl == btnMultiColumnSearchClear.ID ||
                    sSourceControl == "LinkButtonSelect" ||
                    sSourceControl == "ImageButtonNext" ||
                    sSourceControl == "ImageButtonPrev" ||
                    sSourceControl == "ImageButtonFirst" ||
                    sSourceControl == "ImageButtonLast" ||
                    sSourceControl == "DropDownListPageSize" ||
                    sSourceControl == "TextBoxPage")
                {
                    FKModalPopupExtender.Show();
                }
            }
        }
    
        private string getPostBackControlName()
        {
    
            Control control = null;
            //first we will check the "__EVENTTARGET" because if post back made by       the controls 
            //which used "_doPostBack" function also available in Request.Form collection. 
            string ctrlname = Page.Request.Params["__EVENTTARGET"];
            if (ctrlname != null && ctrlname != String.Empty)
            {
                control = Page.FindControl(ctrlname);
            }
            // if __EVENTTARGET is null, the control is a button type and we need to 
            // iterate over the form collection to find it
            else
            {
                string ctrlStr = String.Empty;
                Control c = null;
                foreach (string ctl in Page.Request.Form)
                {
                    //handle ImageButton they having an additional "quasi-property" in their Id which identifies 
                    //mouse x and y coordinates
                    if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
                    {
                        ctrlStr = ctl.Substring(0, ctl.Length - 2);
                        c = Page.FindControl(ctrlStr);
                    }
                    else
                    {
                        c = Page.FindControl(ctl);
                    }
                    if (c is System.Web.UI.WebControls.Button ||
                             c is System.Web.UI.WebControls.ImageButton)
                    {
                        control = c;
                        break;
                    }
                }
            }
            if (control == null) return "";
            return control.ID;
        }
    
        protected override void OnDataBinding(EventArgs e)
        {
            base.OnDataBinding(e);
    
            string selectedValueString = GetSelectedValueString();
            ListItem item = DropDownList1.Items.FindByValue(selectedValueString);
            if (item != null)
            {
                DropDownList1.SelectedValue = selectedValueString;
            }
    
            var metaForeignKeyColumn = Column as MetaForeignKeyColumn;
    
            // get the association attributes associated with MetaChildrenColumns
            var association = metaForeignKeyColumn.Attributes.
                OfType<System.Data.Linq.Mapping.AssociationAttribute>().FirstOrDefault();
    
            if (metaForeignKeyColumn != null && association != null)
            {
    
                // get keys ThisKey and OtherKey into Pairs
                var keys = new Dictionary<String, String>();
                var seperator = new char[] { ',' };
                var thisKeys = association.ThisKey.Split(seperator);
                var otherKeys = association.OtherKey.Split(seperator);
                for (int i = 0; i < thisKeys.Length; i++)
                {
                    keys.Add(otherKeys[i], thisKeys[i]);
                }
    
                // setup the where clause 
                // support composite foreign keys
                foreach (String fkName in metaForeignKeyColumn.ForeignKeyNames)
                {
                    // get the current pk column
                    var fkColumn = metaForeignKeyColumn.ParentTable.GetColumn(fkName);
    
                    // setup parameter
                    var param = new Parameter();
                    param.Name = fkColumn.Name;
                    param.Type = fkColumn.TypeCode;
    
                    // get the PK value for this FK column using the fk pk pairs
                    param.DefaultValue = Request.QueryString[keys[fkName]];
    
                    // add the where clause
                    FKGridDataSource.WhereParameters.Add(param);
                }
            }
            // doing the work of this above because we can't
            // set the DynamicDataManager table or where values
            //DynamicDataManager1.RegisterControl(GridView1, false);
        }
    
        protected override void ExtractValues(IOrderedDictionary dictionary)
        {
            // If it's an empty string, change it to null
            string value = DropDownList1.SelectedValue;
            if (String.IsNullOrEmpty(value))
            {
                value = null;
            }
    
            ExtractForeignKey(dictionary, value);
        }
    
        public override Control DataControl
        {
            get
            {
                return DropDownList1;
            }
        }
    
        protected void Image1_Click(object sender, ImageClickEventArgs e)
        {
            FKModalPopupExtender.Show();
        }
    
        protected void Page_Init(object sender, EventArgs e)
        {
            var metaForeignKeyColumn = Column as MetaForeignKeyColumn;
            var attribute = Column.Attributes.OfType<ShowColumnsAttribute>().SingleOrDefault();
    
            if (attribute != null)
            {
                if (!attribute.EnableDelete)
                    EnableDelete = false;
                if (!attribute.EnableUpdate)
                    EnableUpdate = false;
                if (attribute.DisplayColumns.Length > 0)
                    DisplayColumns = attribute.DisplayColumns;
            }
    
            if (metaForeignKeyColumn != null)
            {
                FKGridDataSource.ContextTypeName = metaForeignKeyColumn.ParentTable.DataContextType.Name;
                FKGridDataSource.TableName = metaForeignKeyColumn.ParentTable.Name;
    
                // enable update, delete and insert
                FKGridDataSource.EnableDelete = EnableDelete;
                FKGridDataSource.EnableInsert = EnableInsert;
                FKGridDataSource.EnableUpdate = EnableUpdate;
                FKGridView.AutoGenerateDeleteButton = EnableDelete;
                FKGridView.AutoGenerateEditButton = EnableUpdate;
    
                // get an instance of the MetaTable
                table = FKGridDataSource.GetTable();
    
                // Generate the columns as we can't rely on 
                // DynamicDataManager to do it for us.
                FKGridView.ColumnsGenerator = new FieldTemplateRowGenerator(table, DisplayColumns);
    
                // setup the GridView's DataKeys
                String[] keys = new String[metaForeignKeyColumn.ParentTable.PrimaryKeyColumns.Count];
                int i = 0;
                foreach (var keyColumn in metaForeignKeyColumn.ParentTable.PrimaryKeyColumns)
                {
                    keys[i] = keyColumn.Name;
                    i++;
                }
                FKGridView.DataKeyNames = keys;
    
                FKGridDataSource.AutoGenerateWhereClause = true;
            }
            else
            {
                // throw an error if set on column other than MetaChildrenColumns
                throw new InvalidOperationException("The GridView FieldTemplate can only be used with MetaChildrenColumns");
            }
    
            SetupMultiColumnSearch();
        }
    
        private void SetupMultiColumnSearch()
        {
            // get multi column search attribute
            //var multiColumnSearch = table.GetAttribute<MultiColumnSearchAttribute>();
            string searchCols = "";
            foreach (var col in table.Columns)
            {
                if (col.GetType() == typeof(MetaChildrenColumn)) continue;
                //{
                //    MetaChildrenColumn mcColumn = (MetaChildrenColumn)col;
                //    foreach (var childCol in mcColumn.ChildTable.Columns)
                //    {
                //        if (!childCol.IsString || childCol.Name.ToLower()!="ime") continue;
                //        if (searchCols == "") searchCols = mcColumn.ChildTable.Name + "." + childCol.Name;
                //        else searchCols += "," + mcColumn.ChildTable.Name + "." + childCol.Name;
                //    }
                //    continue;
                //}
                if (col.IsString == false || col.GetType() == typeof(MetaForeignKeyColumn)) continue;
                if (searchCols == "") searchCols = col.Name;
                else searchCols += "," + col.Name;
            }
    
            if (!string.IsNullOrEmpty(searchCols))
            {
                var searchExpression = new SearchExpression()
                {
                    DataFields = searchCols, //  multiColumnSearch.Columns.ToCsvString(),
                    SearchType = SearchType.Contains
                };
    
                // create control parameter
                var controlParameter = new ControlParameter() { ControlID = txbMultiColumnSearch.ID };
    
                // add control parameter to search expression
                searchExpression.Parameters.Add(controlParameter);
    
                // set context
                searchExpression.SetContext(GridQueryExtender, Context, FKGridDataSource);
    
                // add search expression to query extender
                GridQueryExtender.Expressions.Add(searchExpression);
    
                // make multicolumn search field set visible
                MultiSearchFieldSet.Visible = true;
            }
        }
    
        protected void btnMultiColumnSearch_Click(object sender, EventArgs e)
        {
            var button = (Button)sender;
            if (button.ID == btnMultiColumnSearchClear.ID)
                txbMultiColumnSearch.Text = String.Empty;
        }
    }

    Tuesday, March 29, 2011 5:55 AM

Answers

All replies

  • User-751080518 posted

    Someone?

    Wednesday, March 30, 2011 1:01 AM
  • User-330204900 posted

    Hi there, have a look at my articel here A Popup Insert control for Dynamic Data not exactly the same but you should be able to adapt it for your requirements [:)]

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, March 30, 2011 3:48 AM
  • User-751080518 posted
    Thank you for this peace of code! I will try to modify it for my needs.
    Wednesday, March 30, 2011 1:27 PM
  • User-330204900 posted

    You are welcome [:)]

    Wednesday, March 30, 2011 1:56 PM