2015-08-17 2 views
0

Почему MessageBox и CheckBox учитываются в Design-Time при изменении значения свойства First и не при добавлении элемента во Второе?WinForms - UserControl - List <bool> a Collection <bool> как доступное свойство UserControl

private string _first; 
    [Description(""), Category("GostcompSettings"), DefaultValue("27017")] 
    public string First 
    { 
     get { return __first; } 
     set 
     { 

      _searchAreasChceckBoxList.Clear(); 
      pPanelWithCheckboxies.Controls.Clear(); 
      int x = 10; 
      int y = 10; 

      CheckBox _tempCheck = new CheckBox(); 
      _tempCheck.Checked = true; 
      _tempCheck.Location = new Point(x, y); 

      _searchAreasChceckBoxList.Add(_tempCheck); 
      pPanelWithCheckboxies.Controls.Add(_tempCheck); 

      MessageBox.Show("zmiana"); 
      _first = value; 
     } 
    } 


    private Collection<bool> _second= new Collection<bool>(); 
    [Description(""), Category("*")] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
    public Collection<bool> Second 
    { 
     get 
     { 
      return _second; 
     } 
     set 
     { 

      _searchAreasChceckBoxList.Clear(); 
      pPanelWithCheckboxies.Controls.Clear(); 
      int x = 10; 
      int y = 10; 

      CheckBox _tempCheck = new CheckBox(); 
      _tempCheck.Checked = true; 
      _tempCheck.Location = new Point(x, y); 

      _searchAreasChceckBoxList.Add(_tempCheck); 
      pPanelWithCheckboxies.Controls.Add(_tempCheck); 

      MessageBox.Show("*"); 
      _second= value; 
     } 
    } 

Это тот же сценарий, когда я меняю Collection к списку ... Значения сохраняются (или добавлены к коллекции во Второй случай) и конструктор генерировать код для InitializeComponent().

EDIT после @taffer answear

public class SearchAreaInfo 
{ 
    public SearchAreasEnum searchArea 
    { 
     get; set; 
    } 
} 

public class SearchAreaInfoCollection : Collection<SearchAreaInfo> 
{ 
    private Panel _checkboxParent; 

    public SearchAreaInfoCollection(Panel checkboxParent) : base() 
    { 
     _checkboxParent = checkboxParent; 
    } 

    // called on Add/Insert 
    protected override void InsertItem(int index, SearchAreaInfo item) 
    { 
     base.InsertItem(index, item); 
     RepaintChackboxPanel(); 
    } 

    // called on Remove/RemoveAt 
    protected override void RemoveItem(int index) 
    { 
     base.RemoveItem(index); 
     RepaintChackboxPanel(); 
    } 

    // called when an element is set by the indexer 
    protected override void SetItem(int index, SearchAreaInfo item) 
    { 
     base.SetItem(index, item); 
     RepaintChackboxPanel(); 
    } 

    private void RepaintChackboxPanel() 
    { 
     //_searchAreasChceckBoxList.Clear(); 
     _checkboxParent.Controls.Clear(); 
     int x = 0; 
     int y = 0; 

     foreach (var item in this) 
     { 
      CheckBox _tempCheck = new CheckBox(); 
      _tempCheck.Checked = true; 
      _tempCheck.Location = new Point(x, y); 
      _tempCheck.BringToFront(); 

      //_searchAreasChceckBoxList.Add(_tempCheck); 
      _checkboxParent.Controls.Add(_tempCheck);     
      x += 5; 
      y += 5; 
     } 
     _checkboxParent.Invalidate(); 
    } 
} 

    private SearchAreaInfoCollection _searchAreas; 
    [Description(""), Category("GostcompSettings")] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
    public SearchAreaInfoCollection SearchAreas 
    { 
     get 
     { 
      return _searchAreas; 
     } 
    } 

Теперь prooblem является то, что: когда я добавить, скажем, третий элемент в коллекции в редакторе он рисует только один флажок, но должен сделать 3 флажков ... Кроме того, в отладка Я вижу, что цикл foreach проходит 3 раза: 1-я коллекция имеет 1 элемент, 2-й тайм-сбор имеет 2 элемента, а третья коллекция времени имеет 3 элемента, но, наконец, я вижу только один флажок в _checkboxPanel.

ответ

1

Поскольку установщик Second недвижимости выполнен только при замене всей коллекции. Когда вы добавляете/удаляете элемент, геттер возвращает ваш экземпляр коллекции (_second), а метод Add/Remove будет вызываться в этом экземпляре объекта.

Если вы хотите выполнить проверку на элемент добавления/удаления, создать пользовательский тип коллекции вместо:

public class MyBoolCollection: Collection<bool> 
{ 
    // called on Add/Insert 
    protected override void InsertItem(int index, bool item) 
    { 
     // do some checks here 
     base.InsertItem(index, item); 
    } 

    // called on Remove/RemoveAt 
    protected override void RemoveItem(int index) 
    { 
     // do some checks here 
     base.RemoveItem(index, item); 
    } 

    // called when an element is set by the indexer 
    protected override void SetItem(int index, bool item) 
    { 
     // do some checks here 
     base.SetItem(index, item); 
    } 
} 
+0

Пожалуйста, взгляните на мое редактирование @taffer –

+0

Существует также некоторое неудобство. Когда я нажимаю кнопку «Добавить» в «Редакторе коллекции», он всегда вызывает «InsertItem». При нажатии кнопки «Удалить» вызывает «RemoveItem» только при нажатии «ОК» при выходе из «Редактора коллекции». –

+0

К комментарию раньше. Я заметил, что большинство людей переопределяют методы «Добавить и очищать». Поэтому я думаю, что это работает так, что когда мы удаляем один элемент, он очищает всю коллекцию, а затем снова добавляет элементы N-1 ... –

1

Встроенный редактор коллекции, которые вы используете в настоящее время только изменяет содержание вашей коллекции объект. Это прекрасно работает, но не вызывает звонка вашего звонящего вообще. Другими словами, он никогда не создает новый объект коллекции и не знает, как это сделать.

Чтобы вызвать ваш вызывающий объект, вы должны создать свой собственный UITypeEditor и вернуть его новую коллекцию из переопределения метода EditValue(). Довольно легко сделать, сначала добавить ссылку на System.Design, а затем сделать ваш код выглядеть примерно так:

using System.Drawing.Design; 
... 
     [Editor(typeof(MyEditor), typeof(System.Drawing.Design.UITypeEditor))] 
     public Collection<bool> Second { 
      // etc... 
     } 

     private class MyEditor : UITypeEditor { 
      public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { 
       return UITypeEditorEditStyle.Modal; 
      } 
      public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { 
       var editor = new System.ComponentModel.Design.CollectionEditor(typeof(Collection<bool>)); 
       var retval = (Collection<bool>)editor.EditValue(context, provider, value); 
       return new Collection<bool>(retval); 

      } 
     } 

Вы, вероятно, хотите, чтобы улучшить это немного, как осуществление ваш собственный редактор пользовательского интерфейса, так что все эти BOOLS легче интерпретировать.

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