Написал собственный компонент (наследуется от component), который непосредственно размещает пользователь в DesignTime.
У этого компонента есть свойство ImageList.
Также у компонента есть свойство — коллекция дочерних элементов (дочерние элементы тоже наследуются от component).
Коллекция представляет собой строго типизированную коллекцию от CollectionBase, для редактирования используется стандартный CollectionEditor.
Чтобы коллекция нормально сериализовалась в код написал также TypeConverter.
У элементов коллекции есть свойство ImageIndex (для его редактирования используется стандартный ImageIndexEditor), нужно чтобы при редактировании поля ImageIndex конкретного элемента коллекции в DesignTime в него подставлялись изображения из ImageList родительского компонента, в котором хранится коллекция.
Самый простой способ, до которого я додумался, сделать у каждого элемента коллекции свойство ImageList, которое будет являться ссылкой ImageList родительского компонента, тогда ImageIndexEditor будет работать как надо.
Теперь собственно сам вопрос: Как и в какой момент передать во вновь создаваемый элемент коллекции ImageList родительского компонента?
Нужно чтобы сразу после нажатия кнопки Add в CollectionEditor у вновь созданного элемента сразу же появился ImageList родительского компонента.
Пробовал делать это в методе Add (и AddRange) коллекции, но ImageList в DesignTime режиме не передавался.
Извиняюсь за немного путанную формулировку.
Re: Проблема с DesignTime редактированием собственного компо
Здравствуйте, xdfvjm, Вы писали:
X>Пробовал делать это в методе Add (и AddRange) коллекции, но ImageList в DesignTime режиме не передавался. X>Извиняюсь за немного путанную формулировку.
попробуй переопределить метод OnInsertComplete в CollectionBase. Он будет вызываться при добавлении нового элемента в дизайнере.
... << RSDN@Home 1.1.4 beta 4 rev. 328>>
Старый глюк лучше новых двух!
Re[2]: Проблема с DesignTime редактированием собственного ко
Здравствуйте, Al-Ko, Вы писали:
AK>попробуй переопределить метод OnInsertComplete в CollectionBase. Он будет вызываться при добавлении нового элемента в дизайнере.
Спасибо, то что нужно
Re[3]: Проблема с DesignTime редактированием собственного ко
У меня возник еще один вопрос. Элементы коллекции наследуются от Component, без этого они не сериализуются в код.
Но, когда я удаляю сам родительский компонент, содержащий коллекцию, элементы коллекции не удаляются, а остаются в коде.
Как бы сделать так, чтобы элемент коллекции сериализовался в код без наследования его от Component, ну или сделать так, чтобы он удалялся, когда удаляется родительский компонент?
Re[4]: Проблема с DesignTime редактированием собственного ко
(см.раздел "Сериализация простых классов")
X>ну или сделать так, чтобы он удалялся, когда удаляется родительский компонент?
думаю, если сделаешь, как в статье, все будет правильно удаляться.
там один класс написан на MC++, вот его шарповская версия:
public class InstanceDescriptorBuilder
{
private ArrayList _types = null;
private ArrayList _args = null;
private Type _type;
private object _obj;
private PropertyDescriptorCollection _pdc;
public InstanceDescriptorBuilder(object obj)
{
_type = obj.GetType();
_obj = obj;
_types = new ArrayList();
_args = new ArrayList();
_pdc = TypeDescriptor.GetProperties(obj);
}
public bool IsValueDefault(string property)
{
AttributeCollection attributes =
_pdc[property].Attributes;
DefaultValueAttribute defAttribute =
(DefaultValueAttribute)attributes[typeof(
DefaultValueAttribute)];
return _pdc[property].GetValue(_obj).Equals(defAttribute.Value);
}
public void Add(object obj)
{
_types.Add(_obj.GetType());
_args.Add(_obj);
}
public InstanceDescriptor ToInstanceDescriptor()
{
Type[] types = Type.EmptyTypes;
if (_types.Count > 0)
{
types = new Type[_types.Count];
_types.CopyTo(types);
}
ConstructorInfo ci = _type.GetConstructor(types);
object[] args = null;
if (_args.Count > 0)
{
args = new object[_args.Count];
_args.CopyTo(args);
}
return new InstanceDescriptor(ci, args);
}
}
... << RSDN@Home 1.1.4 beta 4 rev. 328>>
Старый глюк лучше новых двух!
Re[5]: Проблема с DesignTime редактированием собственного ко
Эту статью я уже читал, так тоже можно, но мне не совсем подходит. Дело в том, что элементы коллекции будут со временем обрастать различными свойствами, и не хотелось бы каждый раз при добавлении нового свойства писать новый конструктор в классе+изменять TypeConvertor.
Хотелось бы сделать так, почти как с TabControl — при добавлении TabPage в коде видится следующее:
...
//сначало идет инициализация TabControlthis.tabControl1.Name = "tabControl1";
...
//затем инициализация всех его TabPagethis.tabPage1.Name = "tabPage1";
...
То есть TabPage становится свойством формы, в этом случае отпадает потребность в дополнительных конструкторах и изменениях в TypeConvertor-е
Если наследовать элемент коллекции от Component, то все сериализуется как надо, подобно TabControl, но в этом случае при удалении родительского компонента элементы его коллекции не удаляются и остаются свойствами формы. То есть мне нужно после удаления элемента из коллекции удалить его из свойств формы.
Повозился с CollectionEditor, оказалось, что при любом изменении состава коллекции сначала вызывается OnClear(), затем несколько раз (по количеству элементов) OnInsertComplete(). Попробовал было сделать так:
protected override void OnClear()
{
if (Count>0)
{
IContainer ManagerContainer=List[0].Container;
foreach (Component c in List)
{
ManagerContainer.Remove(c);
}
}
base.OnClear ();
}
Надеясь, что после этого при срабатывании Insert-ов оставшиеся элементы добавятся в Container сами собой. Они действительно добавились, но: во-первых, у них пропало Name (вместо него они стали называться по имени класса), хотя значения свойств сохранились; во-вторых, сериализироваться в код они перестали. Получается, что OnClear() не подходит, а другого события, которое вызывалось бы после добавления всех элементов после изменения коллекции я не нашел. В идеале надо удалить лишние элементы из свойств формы в событии "нажатие кнопки ОК в CollectionEditor", как бы мне это событие отловить? Может нужно унаследовать свой CollectionEditor? Может кто-то сталкивался с подобной проблемой...
Re[6]: Проблема с DesignTime редактированием собственного ко
Здравствуйте, xdfvjm, Вы писали:
X> Дело в том, что элементы коллекции будут со временем обрастать различными свойствами, и не хотелось бы каждый раз при добавлении нового свойства писать новый конструктор в классе+изменять TypeConvertor.
если элемент коллекции — не компонент, то только через новый конструктор + изменения в TypeConvertor. Это, так сказать, классика. X>Хотелось бы сделать так, почти как с TabControl — при добавлении TabPage в коде видится следующее: X>То есть TabPage становится свойством формы, в этом случае отпадает потребность в дополнительных конструкторах и изменениях в TypeConvertor-е
ну естественно, ведь TabPage — компонент.
X>Если наследовать элемент коллекции от Component, то все сериализуется как надо, подобно TabControl, но в этом случае при удалении родительского компонента элементы его коллекции не удаляются и остаются свойствами формы.
кстати, непонятно, почему. Придется, наверное постить тебе сюда код.
Вот, кстати, еще про сериализацию коллекции из компонентов: здесь. Правда, там коллекция самопальная, на IList'е.
X>То есть мне нужно после удаления элемента из коллекции удалить его из свойств формы. X> В идеале надо удалить лишние элементы из свойств формы в событии "нажатие кнопки ОК в CollectionEditor", как бы мне X>это событие отловить? Может нужно унаследовать свой CollectionEditor? Может кто-то сталкивался с подобной проблемой...
во-первых, можно посмотреть в сторону ISupportInitialize для твоего контрола, а во-вторых, правильно, можно и "поработать" с редактором коллекции. Особенно переопределив метод DestroyInstance для твоего случая.
Вся проблема из-за того, что редактор коллекции почему-то не хочет сотрудничать с CollectionBase.
... << RSDN@Home 1.1.4 beta 4 rev. 328>>
Старый глюк лучше новых двух!
Re[3]: Проблема с DesignTime редактированием собственного ко
После долгих мук проб и ошибок проблема решилась до обидного довольно просто, в родительском компоненте (в котором коллекция Buttons лежит) надо добавить уничтожение кнопок в Dispose
Если удалять элемент коллекции из CollectionEditor, то он автоматически удаляется и из формы. Однако, если удалить весь родительский компонент (в котором коллекция), то Visual Studio не считает нужным удалять из формы элементы коллекции, которые без родительского элемента нафиг не нужны. приведенный выше код это исправляет.
Re[7]: Проблема с DesignTime редактированием собственного ко
От:
Аноним
Дата:
04.03.05 20:21
Оценка:
В начале упоминался ImageIndexEditor
Где ты его взял?
родной System.Windows.Forms.ImageIndexEditor не объявлен как public
я когда пожожий контрол писат то и ImageIndexEditor тоже свой делал.
Здравствуйте, Аноним, Вы писали:
А>В начале упоминался ImageIndexEditor
А>Где ты его взял?
А>родной System.Windows.Forms.ImageIndexEditor не объявлен как public
А>я когда пожожий контрол писат то и ImageIndexEditor тоже свой делал.
А>Или я чегото недосмотрел?
Он действительно не public, но это не мешает его использовать, вот аттрибуты:
[Editor("System.Windows.Forms.Design.ImageIndexEditor",typeof(UITypeEditor)),TypeConverter(typeof(ImageIndexConverter)),DefaultValue(-1)]
public int NormalImageIndex
Re[8]: Проблема с DesignTime редактированием собственного ко
От:
Аноним
Дата:
05.03.05 14:01
Оценка:
Попрововал, почти получилось
Т.е. определил ImageList свойство, указывающее на ImageList родителя,
Определил атрибут у ImageIndex
В дизайнере комбо с имеджами заполняется но странно,
индексы видно, а картинок нет.