Почему бы не создать редактор для этого ???Вы думаете, что это звучит излишне, но на самом деле это не так.
Я продемонстрирую на примере.
Описание образца
В этом примере я создам элемент управления с именемButtonActivityControl
, который может сделать несколько ссылок на другие элементы управления в одной форме, используя свойство Buttons
, которое является массивом типа Button (т.е. Button[]
).
Свойство помеченос помощью специального редактора, который позволяет легко ссылаться на элементы управления на странице.В редакторе отображается форма, состоящая из флажка со списком, который используется для выбора нескольких элементов управления в одной и той же форме.
Шаги для создания образца
1) Форма с именемReferencesCollectionEditorForm
- поместите внутри него CheckedListBox,
- поместите кнопку 'ОК'
- поместите следующий код в класс формы
Код ссылкиCollectionEditorForm:
public partial class ReferencesCollectionEditorForm : Form
{
public ReferencesCollectionEditorForm(Control[] available, Control[] selected)
{
this.InitializeComponent();
List<Control> sel = new List<Control>(selected);
this.available = available;
if (available != null)
foreach (var eachControl in available)
this.checkedListBox1.Items.Add(new Item(eachControl),
selected != null && sel.Contains(eachControl));
}
class Item
{
public Item(Control ctl) { this.control = ctl; }
public Control control;
public override string ToString()
{
return this.control.GetType().Name + ": " + this.control.Name;
}
}
Control[] available;
public Control[] Selected
{
get
{
List<Control> selected = new List<Control>(this.available.Length);
foreach (Item eachItem in this.checkedListBox1.CheckedItems)
selected.Add(eachItem.control);
return selected.ToArray();
}
}
}
2) UITypeEditor
Код ссылкиCollectionEditor:
public class ReferencesCollectionEditor : UITypeEditor
{
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
List<Control> available = new List<Control>();
ButtonActivityControl control = context.Instance as ButtonActivityControl;
IDesignerHost host = provider.GetService(typeof(IDesignerHost)) as IDesignerHost;
IComponent componentHost = host.RootComponent;
if (componentHost is ContainerControl)
{
Queue<ContainerControl> containers = new Queue<ContainerControl>();
containers.Enqueue(componentHost as ContainerControl);
while (containers.Count > 0)
{
ContainerControl container = containers.Dequeue();
foreach (Control item in container.Controls)
{
if (item != null && context.PropertyDescriptor.PropertyType.GetElementType().IsAssignableFrom(item.GetType()))
available.Add(item);
if (item is ContainerControl)
containers.Enqueue(item as ContainerControl);
}
}
}
// collecting buttons in form
Control[] selected = (Control[])value;
// show editor form
ReferencesCollectionEditorForm form = new ReferencesCollectionEditorForm(available.ToArray(), selected);
form.ShowDialog();
// save new value
Array result = Array.CreateInstance(context.PropertyDescriptor.PropertyType.GetElementType(), form.Selected.Length);
for (int it = 0; it < result.Length; it++)
result.SetValue(form.Selected[it], it);
return result;
}
}
3) элемент управления, который использует другие элементы управления в той же форме
Код пользовательского элемента управления:
public class ButtonActivityControl : Control, ISupportInitialize
{
[Editor(typeof(ReferencesCollectionEditor), typeof(UITypeEditor))]
public Button[] Buttons { get; set; }
Dictionary<Button, bool> map = new Dictionary<Button, bool>();
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.FillRectangle(Brushes.White, e.ClipRectangle);
if (this.Site != null) return; // this code is needed otherwise designer crashes when closing
int h = e.ClipRectangle.Height / this.Buttons.Length;
int top = 0;
foreach (var button in this.Buttons)
{
e.Graphics.FillRectangle(map[button] ? Brushes.Black : Brushes.White, new Rectangle(0, top, e.ClipRectangle.Width, h));
top += h;
}
base.OnPaint(e);
}
void ISupportInitialize.BeginInit()
{
}
void ISupportInitialize.EndInit()
{
if (this.Site != null) return; // this is needed so that designer does not change the colors of the buttons in design-time
foreach (var button in this.Buttons)
{
button.Click += new EventHandler(button_Click);
button.ForeColor = Color.Blue;
map[button] = false;
}
}
void button_Click(object sender, EventArgs e)
{
map[(Button)sender] = !map[(Button)sender];
this.Invalidate();
}
}
Теперь создайте форму, которая будет содержать пользовательский элемент управления, поместите некоторыекнопки на нем, а затем поместите ButtonActivityControl на него.У пользовательского элемента управления есть свойство Buttons, которое можно редактировать.
Вот и все !!
Нет причин бояться пользовательских редакторов ... и не так сложно .... разделите его пополамчас.
Я думаю, что это ответ ... то есть, я думаю, что это так!=) Может быть, я плохо понял вопрос ... но это лучшее, что можно сделать: пытаясь помочь другим!
РЕДАКТИРОВАТЬ
Этот код нуженв ReferencesCollectionEditor:
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override bool GetPaintValueSupported(ITypeDescriptorContext context)
{
return false;
}