C # Winforms Конструктор Visual Studio не может найти пользовательский тип - PullRequest
0 голосов
/ 13 января 2011

У меня есть пользовательский элемент управления с общим списком пользовательских типов.Этот список является общедоступным:

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

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

Ошибка 1 Не удалось найти тип дляназвание.Имя типа было «ButtonPanelX.CompactButton, ButtonPanelX, версия = 1.0.0.0, культура = нейтральная, PublicKeyToken = ноль».Строка 127, позиция 5. D: \ Projecten \ ButtonPanelX \ ButtonPanelX \ Form1.resx 127 5 ButtonPanelX

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

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

Редактировать:

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

РЕДАКТИРОВАТЬ 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);
    }
}

1 Ответ

2 голосов
/ 13 января 2011

Вместо того, чтобы сериализовать ваши кнопки в файле ресурсов, вы можете попытаться сериализовать их в код позади.Для этого вам нужно реализовать пользовательский TypeDescriptor для вашего типа CompactButton и обработать преобразование в InstanceDescriptor.Посмотрите на Как реализовать 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 .

UPDATE : что касается вашего 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 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...