Ответ 1
Почему бы не создать редактор для этого? Вы думаете, что это звучит излишне, но на самом деле это не так.
Я продемонстрирую с образцом.
Пример описания
В этом примере я создам элемент управления с именем 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
Код ссылкиКоллекцияEditor:
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. Пользовательский элемент управления имеет свойство "Кнопки", которое доступно для редактирования.
Что это!
Нет причин опасаться таможенных редакторов... и не так сложно.... через полчаса.
Я думаю, что это ответ... то есть, я думаю, что это так! =) Возможно, я плохо понял вопрос... но это лучшее, что можно сделать: пытаться помочь другим!
ИЗМЕНИТЬ
Этот код необходим в ReferencesCollectionEditor:
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override bool GetPaintValueSupported(ITypeDescriptorContext context)
{
return false;
}