I'm creating a custom control that lays out radio buttons (No it doesn't have to be radio buttons. I'm just trying to learn how to do this so I can make some more complex stuff down the road that may contain multiple lists of controls) which are added through the Items property (similar to some other controls).
I can build the project, drag this onto a form from the component panel and add radio buttons via the Items property. Unfortunately this is not updated in designer unless you either:
At first I had the logic that puts these on the form contained in the constructor after Initialize but that wasn't working so I moved to to Form_Load.
What am I missing? The above options are just short term workarounds, not solutions.
RBLTest.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WFCL_Library
{
public partial class RBLTest : UserControl
{
private List<RadioButton> _items;
private int leftSpacing = 100;
private int topSpacing = 25;
public RBLTest()
{
_items = new List<RadioButton>();
InitializeComponent();
}
private void RadioButtonList_Load(object sender, EventArgs e)
{
int curLeftPos = 0;
int curTopPos = 0;
foreach (RadioButton rb in _items)
{
rb.Location = new Point(curLeftPos, curTopPos);
rb.Size = new Size(85, 17);
curLeftPos += leftSpacing;
if (curLeftPos > this.Width)
{
curLeftPos = 0;
curTopPos += topSpacing;
}
this.Controls.Add(rb);
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<RadioButton> Items
{
get
{
return _items;
}
set
{
_items = value;
}
}
}
}
RBLTest.Designer.cs
namespace WFCL_Library
{
partial class RBLTest
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// RBLTest
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "RBLTest";
this.Size = new System.Drawing.Size(407, 44);
this.Load += new System.EventHandler(this.RadioButtonList_Load);
this.ResumeLayout(false);
}
#endregion
}
}
You should't use the Load
event or the constructor, because when you add the control with the designer tool an instance of the UserControl
is created and the Load
event is fired. In your case when this happens _item
is still empty. Another issue is that there are some problems serializing a list, so I'd use an array:
public partial class RBLTest : UserControl {
private RadioButton[] _items;
private int leftSpacing = 100;
private int topSpacing = 25;
public RBLTest( ) {
InitializeComponent( );
}
[DesignerSerializationVisibility( DesignerSerializationVisibility.Content )]
public RadioButton[] Items {
get {
return _items;
}
set {
_items = value;
int curLeftPos = 0;
int curTopPos = 0;
foreach ( RadioButton rb in _items ) {
rb.Location = new Point( curLeftPos, curTopPos );
rb.Size = new Size( 85, 17 );
curLeftPos += leftSpacing;
if ( curLeftPos > this.Width ) {
curLeftPos = 0;
curTopPos += topSpacing;
}
this.Controls.Add( rb );
}
}
}
}
The result in the Form Designer:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With