2011-01-13 15 views
0

Ich habe ein benutzerdefiniertes Steuerelement mit einer allgemeinen Liste von benutzerdefinierten Typen. Diese Liste ist öffentlich definiert:C# Winforms Visual Studio-Designer kann benutzerdefinierten Typ nicht finden

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

Als ich dieses Steuerelement zu meiner Form hinzufügen und bauen mein Projekt, das ich diesen Fehler:

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

Wenn ich Strings statt benutzerdefinierte Objekte verwenden, wird die desginer sparen meine Liste. CompactButton hat das Attribut [Serializable] und leitet sich von ISerializable

Was kann ich tun, um das zu beheben?

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

ist Ihr Typ namens * CompactButton * oder * CompactButtons *? In Ihrem Code-Snippet bezeichnen Sie es als CompactButton, während Sie in Ihrem Fragetext CompactButtons sagen. –

+0

Mein Typ heißt 'CompactButton'. Ich habe meine Frage bearbeitet. – Martijn

+0

Was ist die Ziel-Framework-Version für Ihr Projekt? Google sagt, dass es einige Probleme gibt, wenn das Ziel das 3.5-Framework ist. – Patko

Antwort

2

Statt die Tasten auf die Ressource-Datei von Serialisierung, könnten Sie versuchen, sie zurück den Code zu serialisieren. Dazu müssen Sie eine benutzerdefinierte TypeDescriptor für Ihren Typ implementieren und dort eine Umwandlung in eine InstanceDescriptor Handle. Schauen Sie sich How to Implement a TypeConverter an. Beispiel:

[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);  
    } 

} 

Für weitere Informationen siehe auch die InstanceDescriptor Klasse.

UPDATE: Wie für Ihre UITypeEditor und die CompactButtons-Eigenschaft, benötigen Sie keinen Setter. Ändern Sie Ihre CompactButtons Eigenschaft wie folgt:

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

Dann Sie die EditValue Methode von UITypeEditor wie so implementieren könnte:

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; 
} 

Wenn Ihr Editor Formular Sie vielleicht nicht sehr spezialisiert könnte die CollectionEditor ausprobieren.

+0

Was meinst du mit Serialisierung auf den Code hinter? Wie kann ich das machen? Können Sie einen kleinen Beispielcode posten? – Martijn

+0

Vielen Dank für ein Beispiel. Aber ich verstehe immer noch nicht, wie ich das nutzen kann. Wo findet die Serialisierung statt? Wo muss ich das machen? Wie kann ich den Code dahinter öffnen? Es tut mir leid, aber es klingt wie Chinesisch für mich. (und ich komme aus Holland :)) – Martijn

+0

Code hinter Winforms ist in der Designer-Datei, in Ihrem Fall sollten Sie ein Form1.Designer.cs haben.Darin ist eine partielle Klassendefinition enthalten, die die InitializeComponent-Methode enthält, und alles, was Sie im Formular-Designer ändern, wird als Code für diese Methode oder für die Ressourcendatei serialisiert, wenn der serialisierte Typ die CodeDom-Serialisierung nicht unterstützt. – Patko

Verwandte Themen