skip to Main Content

I need a Server Control (named FormLayout here) that renders child controls based on their attribute.

The goal is to be able to write something like the following:

<custom:FormLayout runat="server" ID="myForm">
   <custom:MyDropDownList runat="server" ID="field1" ColumnSpan="12"></custom:MyDropDownList>
   <custom:MyTextBox runat="server" ID="field2"></custom:MyTextBox>
</custom:FormLayout>

This is the current implementation for these server controls: (In reality there will be more types of child server control, not only these two.)

public interface ICommonFieldProperties{
  public int ColumnSpan {get;set;}
}
public class MyDropDownList:System.Web.UI.WebControls.DropDownList,
 ICommonFieldProperties {
  public int ColumnSpan {get;set;}
}

public class MyTextBox:System.Web.UI.WebControls.TextBox,
 ICommonFieldProperties {
  public int ColumnSpan {get;set;}
}

public class FormLayout:Panel{
protected override void RenderContents(HtmlTextWriter writer){
 foreach (Control i in Controls)
    // can't access the newly added common properties such as "ColumnSpan"
    i.RenderControl(writer);
}

I tried to add the common properties by inheriting a common interface, but then I need to cast these child controls to ICommonFieldProperties whenever I want to access properties defined in it and cast them back to Control whenever I want to use the methods inherited from Control. For exmaple:

protected override void RenderContents(HtmlTextWriter writer) {
  var orderedControls = Controls
    .OfType<ICommonFieldProperties>()
    .Where(c => c.ColumnSpan == 0);
  foreach (var field in orderedControls){
    // Group them into different wrappers based on some other common properties  in ICommon Field
    // ...
    // render
    ((Control)field).RenderControl(writer);
  }
}

Another big problem is that since this is on .Net 4.8, interfaces don’t support default methods so I will need to duplicate every implementation for methods/auto properties in ICommonFieldProperties in each child server control even if they are all the same. Is there an easier way to do this?

2

Answers


  1. public partial class MyUserControl: UserControl
    {
      public MyUserControl()
      {
         InitializeComponent();
      }
    user control
       public string FirstName`enter code here`
        {
            get { return FirstNameTextBox.Text; }
            set { FirstNameTextBox.Text = value; }
        }
    
        public string LastName
        {
            get { return LastNameTextBox.Text; }
            set { LastNameTextBox.Text = value; }
        }
    }
    
    public partial class MainWindow: Window
    {
        public MainWindow()
        {
            InitializeComponent();
    
            MyUserControlInstance.FirstName = "John";
            MyUserControlInstance.LastName = "Doe";
    
            string firstName = MyUserControlInstance.FirstName;
            string lastName = MyUserControlInstance.LastName;
        }
    }
    
    Login or Signup to reply.
  2. Separate FormSlot elements from Control elements.

    <custom:FormLayout runat="server" ID="myForm">
    
       <custom:FormSlot ColumnSpan="12">
          <custom:MyDropDownList runat="server" ID="field1" >
          </custom:MyDropDownList>
       </custom:FormSlot>
    
       <custom:FormSlot>
          <custom:MyTextBox runat="server" ID="field2">
          </custom:MyTextBox>
       </custom:FormSlot>
    
    </custom:FormLayout>
    

    Since the common properties you mentioned seem to be all layout-related.
    If so, it’s better to abstract the FormSlot from Control itself, which acts more like a container for setting arranging properties such as the ColumnSpan you mentioned above.

    public class FormSlot: PlaceHolder
    {
      public int ColumnSpan {get;set;}
    }
    public class MyDropDownList:System.Web.UI.WebControls.DropDownList
    {
    }
    
    public class MyTextBox:System.Web.UI.WebControls.TextBox
    {
    }
    
    public class FormLayout:Panel
    {
       protected override void RenderContents(HtmlTextWriter writer)
       {
          var slots = Controls
            .OfType<FormSlot>()
            .Where(c => c.ColumnSpan == 0);
          // This way you can access the common properties as FormSlot
       }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search