Проблема с DesignTime редактированием собственного компонент
От: xdfvjm  
Дата: 02.03.05 17:08
Оценка:
Написал собственный компонент (наследуется от 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 редактированием собственного компо
От: Al-Ko  
Дата: 02.03.05 18:35
Оценка:
Здравствуйте, xdfvjm, Вы писали:

X>Пробовал делать это в методе Add (и AddRange) коллекции, но ImageList в DesignTime режиме не передавался.

X>Извиняюсь за немного путанную формулировку.

попробуй переопределить метод OnInsertComplete в CollectionBase. Он будет вызываться при добавлении нового элемента в дизайнере.
... << RSDN@Home 1.1.4 beta 4 rev. 328>>
Старый глюк лучше новых двух!
Re[2]: Проблема с DesignTime редактированием собственного ко
От: xdfvjm  
Дата: 02.03.05 19:45
Оценка:
Здравствуйте, Al-Ko, Вы писали:

AK>попробуй переопределить метод OnInsertComplete в CollectionBase. Он будет вызываться при добавлении нового элемента в дизайнере.


Спасибо, то что нужно
Re[3]: Проблема с DesignTime редактированием собственного ко
От: xdfvjm  
Дата: 02.03.05 20:35
Оценка:
У меня возник еще один вопрос. Элементы коллекции наследуются от Component, без этого они не сериализуются в код.

Но, когда я удаляю сам родительский компонент, содержащий коллекцию, элементы коллекции не удаляются, а остаются в коде.

Как бы сделать так, чтобы элемент коллекции сериализовался в код без наследования его от Component, ну или сделать так, чтобы он удалялся, когда удаляется родительский компонент?
Re[4]: Проблема с DesignTime редактированием собственного ко
От: Al-Ko  
Дата: 03.03.05 09:51
Оценка:
Здравствуйте, xdfvjm, Вы писали:

X>Как бы сделать так, чтобы элемент коллекции сериализовался в код без наследования его от Component,


Так на сайте есть статья: здесь
Автор(ы): Владислав Чистяков
Дата: 09.05.2003
Создание ПО из компонентов подразумевает, что компоненты будут добавляться к проекту во время разработки. При этом будет производиться их начальная настройка. Компоненты как таковые не подразумевают (вернее сказать, не обязаны иметь) пользовательского интерфейса (ни для программиста, ни для конечного пользователя). В этом качестве выступают части IDE и дополнительные программные дизайнеры. Первой компонентной средой был продукт, купленный Microsoft на заре своего существования. Впоследствии на его базе родился VB. Далее была Delphi… в общем, к концу двадцатого века компоненты стали поддерживаться почти везде (даже в Visual C++, хотя он и по сей день не очень-то визуальный).


(см.раздел "Сериализация простых классов")

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 редактированием собственного ко
От: xdfvjm  
Дата: 03.03.05 13:04
Оценка:
Здравствуйте, Al-Ko, Вы писали:

AK>Так на сайте есть статья: здесь
Автор(ы): Владислав Чистяков
Дата: 09.05.2003
Создание ПО из компонентов подразумевает, что компоненты будут добавляться к проекту во время разработки. При этом будет производиться их начальная настройка. Компоненты как таковые не подразумевают (вернее сказать, не обязаны иметь) пользовательского интерфейса (ни для программиста, ни для конечного пользователя). В этом качестве выступают части IDE и дополнительные программные дизайнеры. Первой компонентной средой был продукт, купленный Microsoft на заре своего существования. Впоследствии на его базе родился VB. Далее была Delphi… в общем, к концу двадцатого века компоненты стали поддерживаться почти везде (даже в Visual C++, хотя он и по сей день не очень-то визуальный).


AK>(см.раздел "Сериализация простых классов")


Эту статью я уже читал, так тоже можно, но мне не совсем подходит. Дело в том, что элементы коллекции будут со временем обрастать различными свойствами, и не хотелось бы каждый раз при добавлении нового свойства писать новый конструктор в классе+изменять TypeConvertor.

Хотелось бы сделать так, почти как с TabControl — при добавлении TabPage в коде видится следующее:

...
//сначало идет инициализация TabControl
this.tabControl1.Name = "tabControl1";
...
//затем инициализация всех его TabPage
this.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 редактированием собственного ко
От: Al-Ko  
Дата: 03.03.05 13:38
Оценка:
Здравствуйте, 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 редактированием собственного ко
От: Аноним  
Дата: 03.03.05 05:47
Оценка:
Рекомендую почитать статью http://www.codeproject.com/csharp/DzCollectionEditor.asp
С/у Дмитрий.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[7]: Проблема с DesignTime редактированием собственного ко
От: xdfvjm  
Дата: 04.03.05 16:33
Оценка:
После долгих мук проб и ошибок проблема решилась до обидного довольно просто, в родительском компоненте (в котором коллекция Buttons лежит) надо добавить уничтожение кнопок в Dispose

protected override void Dispose( bool disposing )
{
    if( disposing )
    {
        if (Buttons.Count>0)
        {
            IContainer c=Buttons[0].Container;
            if (c!=null)
            {
                foreach (IComponent Button in Buttons)
                {
                    c.Remove(Button);
                }
            }
        }
        Buttons.Clear();
        if(components != null)
        {
            components.Dispose();
        }
    }
    base.Dispose( disposing );
}


Если удалять элемент коллекции из CollectionEditor, то он автоматически удаляется и из формы. Однако, если удалить весь родительский компонент (в котором коллекция), то Visual Studio не считает нужным удалять из формы элементы коллекции, которые без родительского элемента нафиг не нужны. приведенный выше код это исправляет.
Re[7]: Проблема с DesignTime редактированием собственного ко
От: Аноним  
Дата: 04.03.05 20:21
Оценка:
В начале упоминался ImageIndexEditor

Где ты его взял?

родной System.Windows.Forms.ImageIndexEditor не объявлен как public

я когда пожожий контрол писат то и ImageIndexEditor тоже свой делал.

Или я чегото недосмотрел?


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[8]: Проблема с DesignTime редактированием собственного ко
От: xdfvjm  
Дата: 05.03.05 11:51
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В начале упоминался 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

В дизайнере комбо с имеджами заполняется но странно,
индексы видно, а картинок нет.

Почему???


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.