2011-01-13 2 views
0

У меня есть настраиваемый элемент управления с общим списком настраиваемых типов. Этот список определяется общественностью:C# Winforms Дизайнер Visual Studio не может найти настраиваемый тип

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Editor(typeof(ButtonPanelXEditor), typeof(UITypeEditor))] 
public List<CompactButton> CompactButtons 
{ 
    get { return _compactButtons; } 
    set { _compactButtons = value; } 
} 

Когда я добавить этот элемент управления для моей формы и построить мой проект, я получаю эту ошибку:

Error 1 Could not find a type for a name. The type name was 'ButtonPanelX.CompactButton, ButtonPanelX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Line 127, position 5. D:\Projecten\ButtonPanelX\ButtonPanelX\Form1.resx 127 5 ButtonPanelX

Когда я использую строки вместо пользовательских объектов, то desginer ли сохранить мой список. CompactButton имеет атрибут [Serializable] и берет начало с ISerializable

Что можно сделать, чтобы исправить это?

Edit:

public class ButtonPanelXEditor : UITypeEditor 
{ 
    public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context) 
    { 
     if (context != null && context.Instance != null) 
      // We will use a window for property editing. 
      return UITypeEditorEditStyle.Modal; 

     return base.GetEditStyle(context); 
    } 

    public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, 
     IServiceProvider provider, object value) 
    { 

     context.OnComponentChanging(); 

     ButtonPanel b = context.Instance as ButtonPanel; 

     FooBar form = new FooBar(); 
     form.Buttons = b.CompactButtons; 

     form.ShowDialog(); 

     b.CompactButtons = form.Buttons; 

     b.DrawButtons(); 

     context.OnComponentChanged(); 

     return form.Buttons; 
    } 
} 

EDIT 2:

[Serializable] 
public partial class ButtonPanel : UserControl 
{ 
    private ArrayList _compactButtons; 

    public ButtonPanel() 
    { 
     InitializeComponent(); 

     _compactButtons = new ArrayList(); 

     AddButtons(); 

     this.Load += new EventHandler(ButtonPanel_Load); 

    } 

    void ButtonPanel_Load(object sender, EventArgs e) 
    { 
     DrawButtons(); 
    } 


    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Editor(typeof(ButtonPanelXEditor), typeof(UITypeEditor))] 
    public ArrayList CompactButtons 
    { 
     get { return _compactButtons; } 
    } 

    public void DrawButtons() 
    { 
     baseButton1.Visible = ((CompactButton)_compactButtons[0]).Visible; 
     baseButton2.Visible = ((CompactButton)_compactButtons[1]).Visible; 
    } 

    private void AddButtons() 
    { 
     /* Buttons baseButton1 and baseButton2 are created by the designer */ 

     CompactButton c = new CompactButton(); 
     c.Enabled = baseButton1.Enabled; 
     c.Visible = baseButton1.Visible; 
     c.Name = baseButton1.Name; 

     CompactButton c2 = new CompactButton(); 
     c2.Enabled = baseButton2.Enabled; 
     c2.Visible = baseButton2.Visible; 
     c2.Name = baseButton2.Name; 

     _compactButtons.Add(c); 
     _compactButtons.Add(c2); 
    } 
} 
+0

Ваш тип с именем * CompactButton * или * CompactButtons *? В своем фрагменте кода вы ссылаетесь на него как на CompactButton, в то время как в вашем текстовом вопросе вы указываете CompactButtons. –

+0

Мой тип называется 'CompactButton'. Я отредактировал мой вопрос. – Martijn

+0

Какова целевая версия рамки для вашего проекта? Google говорит, что есть некоторые проблемы, если целью является 3.5. – Patko

ответ

2

Вместо сериализации ваши кнопки в файл ресурсов, вы могли бы попытаться сериализации их в код позади. Для этого вам нужно реализовать пользовательский TypeDescriptor для вашего типа CompactButton и конвертировать дескриптор в InstanceDescriptor. Посмотрите на How to Implement a TypeConverter. Пример:

[TypeConverter(typeof(CompactButtonTypeConverter))] 
public class CompactButton: ... { 
    ... 
} 

public class CompactButtonTypeConverter: TypeConverter { 

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { 
    if (destinationType == typeof(InstanceDescriptor)) 
     return true; 
    return base.CanConvertTo(context, destinationType); 
    } 

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { 
    if (destinationType == typeof(InstanceDescriptor) && value is CompactButton) { 
     // This assumes you have a public default constructor on your type. 
     ConstructorInfo ctor = typeof(CompactButton).GetConstructor(); 
     if (ctor != null) 
     return new InstanceDescriptor(ctor, new object[0], false); 
    } 
    return base.ConvertTo(context, culture, value, destinationType);  
    } 

} 

Для получения более подробной информации также см InstanceDescriptor класса.

ОБНОВЛЕНИЕ: Что касается вашего UITypeEditor и свойства CompactButtons, вам не нужен сеттер. Измените свойство CompactButtons следующим образом:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Editor(typeof(ButtonPanelXEditor), typeof(UITypeEditor))] 
public List<CompactButton> CompactButtons 
{ 
    get { return _compactButtons; } // _compactButtons must of course be initialized. 
} 

Тогда вы могли бы реализовать метод EditValue из UITypeEditor так:

public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, 
    IServiceProvider provider, object value) { 
    if (context == null || provider == null) 
    return null; 

    var b = context.Instance as ButtonPanel; 
    if (b == null) 
    return value; 

    var editorService = (IWindowsFormsEditorService) 
    provider.GetService(typeof(IWindowsFormsEditorService)); 
    if (editorService == null) 
    return null; 

    // This constructor should copy the buttons in its own list. 
    using (var form = new FooBar(b.CompactButtons)) { 
    if (editorService.ShowDialog(form) == DialogResult.OK && context.OnComponentChanging()) { 
     b.CompactButtons.Clear(); 
     b.CompactButtons.AddRange(form.Buttons); 
     context.OnComponentChanged(); 
    } 
    } 
    return value; 
} 

Если редактор форм не очень специализированы вы могли бы, возможно, попробовать CollectionEditor.

+0

Что вы подразумеваете под сериализацией кода? Как я могу это сделать? Можете ли вы разместить небольшой пример кода? – Martijn

+0

Благодарим вас за предоставленный пример. Но я до сих пор не понимаю, как я могу это использовать. Где происходит сериализация? Где мне нужно это сделать? Как я могу открыть код? Извините, но для меня это звучит как китайский. (и я из Голландии :)) – Martijn

+0

Код для winforms находится в файле .Designer, в вашем случае у вас должен быть Form1.Designer.cs.В этом есть определение частичного класса, которое содержит метод InitializeComponent, и все, что вы меняете в дизайнере форм, сериализуется как код этого метода или файл ресурсов, если тип сериализации не поддерживает сериализацию CodeDom. – Patko

Смежные вопросы