Ticket Q434251
Visible to All Users
Duplicate

We have closed this ticket because another page addresses its subject:

How to create a custom ITemplate based on controls provided by built-in XAF PropertyEditors

XAF Web: GridView EditFormTemplate with manually generated column editors fails on Update or Cancel

created 12 years ago

Hello,

I created a EditFormTemplate for my AspxGridView as follows

public class BrennstoffKostenEditForm : ITemplate
{
GridViewEditFormTemplateContainer MyContainer;
public BrennstoffKostenEditForm(){}
void ITemplate.InstantiateIn(Control container)
{
container.Controls.Clear();
MyContainer = container as GridViewEditFormTemplateContainer;

Panel panel = new Panel();
panel.ID = "BrennstoffkostenEditFormMainPanel";

WebPropertyEditor wpeBrennstoff = ((DataItemTemplate)((GridViewDataColumn)MyContainer.Grid.Columns["Brennstoff"]).EditItemTemplate).PropertyEditor;
wpeBrennstoff.ViewEditMode = ViewEditMode.Edit;
wpeBrennstoff.CreateControl();
ASPxLookupPropertyEditor lpeBrennstoff = (ASPxLookupPropertyEditor)((DataItemTemplate)((GridViewDataColumn)MyContainer.Grid.Columns["Brennstoff"]).EditItemTemplate).PropertyEditor;
((ASPxLookupDropDownEdit)lpeBrennstoff.DropDownEdit).AddingEnabled = true;
((ASPxLookupDropDownEdit)lpeBrennstoff.DropDownEdit).ClearingEnabled = false;

WebPropertyEditor wpeBetrag = ((DataItemTemplate)((GridViewDataColumn)MyContainer.Grid.Columns["Betrag"]).EditItemTemplate).PropertyEditor;
wpeBetrag.ViewEditMode = ViewEditMode.Edit;
wpeBetrag.CreateControl();
ASPxDecimalPropertyEditor lpeBetrag = (ASPxDecimalPropertyEditor)((DataItemTemplate)((GridViewDataColumn)MyContainer.Grid.Columns["Betrag"]).EditItemTemplate).PropertyEditor;
((ASPxSpinEdit)lpeBetrag.Editor).SpinButtons.ShowIncrementButtons = false;
((ASPxSpinEdit)lpeBetrag.Editor).DecimalPlaces = 2;
((ASPxSpinEdit)lpeBetrag.Editor).DisplayFormatString = "{0:C2}";


tr1.Cells[0].Controls.Add(lblBrennstoff);

tr2.Cells[2].Controls.Add(lblBetrag);

}
}

I tried this approach because of the complex editors i need.

The Form is displayed as i expected it.
BUT
if i click on Update or Cancel button an error is thrown:

Type: HttpException
     Message: Multiple controls with the same ID '_inactive' were found. FindControl requires that controls have unique IDs.
     Data: 0 entries
     Stack trace:

at System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls)
at System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls)
at System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls)
at System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls)
at System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls)
at System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls)
at System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls)
at System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls)
at System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls)
at System.Web.UI.Control.FindControl(String id, Int32 pathOffset)
at System.Web.UI.Control.FindControl(String id, Int32 pathOffset)
at System.Web.UI.Control.FindControl(String id, Int32 pathOffset)
at System.Web.UI.Control.FindControl(String id, Int32 pathOffset)
at System.Web.UI.Control.FindControl(String id, Int32 pathOffset)
at System.Web.UI.Control.FindControl(String id, Int32 pathOffset)
at System.Web.UI.Control.FindControl(String id, Int32 pathOffset)
at System.Web.UI.Control.FindControl(String id, Int32 pathOffset)
at System.Web.UI.Page.FindControl(String id)
at System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
     InnerException is null

26.09.12 09:56:29.931     2ltln5sth4tqppqyd4qkojrk     Save model changes
26.09.12 09:56:29.932     2ltln5sth4tqppqyd4qkojrk     ===================
26.09.12 09:56:29.940     2ltln5sth4tqppqyd4qkojrk     page_Unload
26.09.12 09:56:29.940     2ltln5sth4tqppqyd4qkojrk     Frame.set_Template: old value - ASP.nestedframecontrol_ascx, new value - null
26.09.12 09:56:29.940     2ltln5sth4tqppqyd4qkojrk     Frame.set_Template: old value - ASP.nestedframecontrol_ascx, new value - null
26.09.12 09:56:29.941     2ltln5sth4tqppqyd4qkojrk     Frame.set_Template: old value - ASP.default_aspx, new value - null
26.09.12 09:56:32.233     2ltln5sth4tqppqyd4qkojrk          preferredLanguageName: (User language)
26.09.12 09:56:32.233     2ltln5sth4tqppqyd4qkojrk          userLanguageName: de
26.09.12 09:56:32.233     2ltln5sth4tqppqyd4qkojrk          Thread.CurrentThread.CurrentUICulture.DisplayName: German (Germany)
26.09.12 09:56:32.233     2ltln5sth4tqppqyd4qkojrk          preferredLanguageName: (User language)
26.09.12 09:56:32.233     2ltln5sth4tqppqyd4qkojrk          userFormattingCultureName: de
26.09.12 09:56:32.233     2ltln5sth4tqppqyd4qkojrk          selectedFormattingCultureName:
26.09.12 09:56:32.233     2ltln5sth4tqppqyd4qkojrk          Thread.CurrentThread.CurrentCulture.DisplayName: German (Germany)
26.09.12 09:56:32.233     2ltln5sth4tqppqyd4qkojrk     Frame.set_Template: old value - null, new value - ASP.default_aspx
26.09.12 09:56:32.246     2ltln5sth4tqppqyd4qkojrk     Frame.set_Template: old value - null, new value - ASP.nestedframecontrol_ascx
26.09.12 09:56:32.247     2ltln5sth4tqppqyd4qkojrk          ListView: ListView, ID:A4v_Abrechnungsperiode_BrennstoffHeiznebenkosten_Brennstoffkosten_ListView
26.09.12 09:56:32.247     2ltln5sth4tqppqyd4qkojrk          ListView.CollectionSource: DevExpress.ExpressApp.PropertyCollectionSource
26.09.12 09:56:32.247     2ltln5sth4tqppqyd4qkojrk          ListView.CollectionSource.List: DevExpress.ExpressApp.ProxyCollection
26.09.12 09:56:32.247     2ltln5sth4tqppqyd4qkojrk     Frame.set_Template: old value - null, new value - ASP.nestedframecontrol_ascx
26.09.12 09:56:32.247     2ltln5sth4tqppqyd4qkojrk          ListView: ListView, ID:A4v_Abrechnungsperiode_BrennstoffHeiznebenkosten_Heiznebenkosten_ListView
26.09.12 09:56:32.247     2ltln5sth4tqppqyd4qkojrk          ListView.CollectionSource: DevExpress.ExpressApp.PropertyCollectionSource
26.09.12 09:56:32.247     2ltln5sth4tqppqyd4qkojrk          ListView.CollectionSource.List: DevExpress.ExpressApp.ProxyCollection

Answers

created 12 years ago (modified 12 years ago)

Hello Juergen,
I believe that the same error will occur without XAF and even without using our controls in a regular ASP.NET application, because you apparently have repeated structures (templates) with controls with the same identifiers. So, at first glance I suggest you specify a unique ID for the Panel control you created, e.g., using Guid.NewGuid.ToString().
Second, and more important, after looking at your code and reviewing your task, I do not quite understand why implementation of a custom EditForm template is required for it. It is not that straightforward and may be unsafe, as we have not tested this scenario in XAF. It may also lead to further errors like the one you encountered. Due to this, I am afraid we will not be able to assist you further in this case.
Instead, my best advice to you is to customize the built-in EditForm controls as you require. You can do this by handling the ASPxGridView.HtmlEditFormCreated event. I remember that a few years ago we had the following code in our product (it is actually an example of handling this event) that may help you today, I hope:

C#
private void Grid_HtmlEditFormCreated(object sender, ASPxGridViewEditFormEventArgs e) { DisableEditFormCells(e); } protected virtual void DisableEditFormCells(ASPxGridViewEditFormEventArgs e) { if (ListEditor.Grid.IsEditing && e.EditForm != null) Accept(e.EditForm, delegate(Control control) { GridViewTableEditorCellBase editCell = control as GridViewTableEditorCellBase; if (editCell != null) DisableEditor(editCell); } ); }

If this approach does not meet your business needs, we would require more information on your ultimate goal, in addition to knowing: "I tried this approach because of the complex editors i need". This will help us suggest the best solution possible in our framework. I want to help you and look forward to hearing from you.

    Show previous comments (2)
    Dennis Garavsky (DevExpress) 12 years ago

      Juergen,
      Thank you for clarifying your scenario. It is now clear to me why you want to use a custom template, and it makes sense.
      In fact, there are already methods for getting built-in editors (including lookups). We use these methods when creating controls for the edit forms of the grid control.
      I described these methods in a recent How to create a custom ITemplate based on controls provided by built-in XAF PropertyEditors ticket.
      I am afraid that this API is undocumented. However, you can find many examples of its use in our source code: …\DevExpress.ExpressApp.Web\
      I hope you find this information helpful.

      JS JS
      Juergen Schmidt 1 12 years ago

        Hello Dennis,
        in my initial posting on this BUG (not a feature) you can find the error message:

        Message: Multiple controls with the same ID '_inactive' were found. FindControl requires that controls have unique IDs.

        In your source code for AspxLookupPropertyEditor you will find at row 420 ff:
        private void UpdateControlId() {
                       if(ActiveControl != null) {
                            ActiveControl.ID = editorId;
                       }
                       if(InactiveControl != null) {
                            InactiveControl.ID = editorId + "_inactive";
                       }
                  }
                  protected override void SetEditorId(string controlId) {
                       this.editorId = controlId;
                       UpdateControlId();
                  }
        Either dropdowneditors or findeditors Id is set to "_inaktive" due to the number of items found in the data collection.
        I got the error message i send you with this ticket due to the fact, that i have more than one ASPxLookupEditor in my template.
        And i found out that the following code with the very important last row will work:
        IModelViewItems modelViewItems = Application.FindModelClass(ObjectType).DefaultDetailView.Items;
        IModelMemberViewItem mvi2 = (IModelMemberViewItem)modelViewItems["MwSt"];
        ViewItem pe2 = (ViewItem)Application.EditorFactory.CreateDetailViewEditor(false, mvi2, ObjectType, Application, ObjectSpace);
        pe2.CurrentObject = MyCurrentObject;
        ((ASPxLookupPropertyEditor)pe2).ViewEditMode = ViewEditMode.Edit;
        pe2.CreateControl();
        ((ASPxLookupPropertyEditor)pe2).SetControlId("MwSt");
        The sad truth is that ASPxLookupPropertyEditor.CreateControl() does not create controls with a unique id.
        Thanks
        Jürgen

        Dennis Garavsky (DevExpress) 12 years ago

          Hey Juergen,
          I must ask you to pardon my not noticing the "ID '_inactive" string from the error message and then not associating it with the underlying control created by our built-in PropertyEditor.
          We do not, however, consider this to be a "bug", sense in standard scenarios supported by XAF there may be more than one lookup editor and it all functions fine. Thus, I advise you just take this modification into account for your current implementation. If you found the same problem with these supported scenarios, please let us know. We will surely consider improving our current implementation.

          Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

          Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.