PropertyGrid FAQ
От: Алексей Кирюшкин Россия http://malgarr.blogspot.com/
Дата: 07.12.06 09:45
Оценка: 2272 (58) +4
Статья:
PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



Авторы:
Алексей Кирюшкин

Аннотация:
Как заменить имя переменной в левой колонке “человеческим” именем свойства?
Как отобразить расширенную подсказку по свойству в нижнем окне?
Как сгруппировать свойства по категориям?
Как отобразить свойство, недоступное для редактирования?
Как заменить стандартные True/False в отображении свойств типа bool?
Как заменить стандартное отображение имен членов перечисления?
Как показать свою картинку для каждого значения из перечисления?
Как организовать выбор значения из выпадающего списка, формируемого программно?
Как реализовать отображение составного свойства?
Как организовать выбор файла с заданным расширением?
Как организовать редактирование свойства в собственной форме?
Как организовать редактирование свойства в выпадающем списке?
Как управлять видимостью свойства в зависимости от значения другого свойства?
Как избавиться от стандартного “(Collection)” в правой колонке для свойств-коллекций?
Как заменить стандартные подписи (Members, properties) в окне Collection Editor?
Как добавить в Collection Editor окно с расширенной подсказкой по редактируемым свойствам?
Как задать отличный от алфавитного порядок следования свойств внутри категории?
Как запомнить и восстановить положение разделителя колонок в PropertyGrid?
propertygrid
Re: PropertyGrid FAQ
От: S.Bludov Украина  
Дата: 16.01.07 16:33
Оценка: 3 (1) +1
Здравствуйте, Алексей Кирюшкин, Вы писали:

АК>Статья:

АК>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



Спасибо за статью.
Как реализовать локализацию свойств в гриде?

Спасибо.
Re[2]: PropertyGrid FAQ
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 17.01.07 04:42
Оценка:
Здравствуйте, S.Bludov, Вы писали:

SB>Как реализовать локализацию свойств в гриде?


этим я еще не заморачивался
... << RSDN@Home 1.2.0 alpha rev. 668>>
Re[2]: PropertyGrid FAQ
От: D.Triton Украина  
Дата: 17.01.07 09:23
Оценка:
Здравствуйте, S.Bludov, Вы писали:

SB>Здравствуйте, Алексей Кирюшкин, Вы писали:


АК>>Статья:

АК>>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



SB>Спасибо за статью.

SB>Как реализовать локализацию свойств в гриде?

SB>Спасибо.


Пример:


[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class DisplayNameLocalizedAttribute : DisplayNameAttribute
    {
        private Type resourceSource;
        private string resourceName;

        protected DisplayNameLocalizedAttribute()
        {
        }

        public DisplayNameLocalizedAttribute(Type resourceSource, string resourceName)
        {
            this.resourceSource = resourceSource;
            this.resourceName = resourceName;
            UpdateDisplayName();
        }

        public void UpdateDisplayName()
        {
            ResourceManager rm = new ResourceManager(resourceSource);
            DisplayNameValue = rm.GetString(resourceName);
        }
    }


Используем так:

public class YearRequestByMonthConfig : BaseReportConfig
    {
        //YearRequestByMonthRptConfigResources - компонент с ресурсами
        [DisplayNameLocalized(typeof (YearRequestByMonthRptConfigResources), "Department")]
        public string Department
        {
            get { return department; }
            set { department = value; }
        }
}
Re[3]: PropertyGrid FAQ
От: S.Bludov Украина  
Дата: 17.01.07 09:24
Оценка:
Здравствуйте, D.Triton, Вы писали:

Спасибо, Стас
Re: PropertyGrid FAQ
От: _FRED_ Черногория
Дата: 17.01.07 16:05
Оценка:
Здравствуйте, Алексей Кирюшкин, Вы писали:

АК>Статья:

АК>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



Спасибо за статью

1. Имхо, часто, к сожелению, забывают в TypeCoverter-ах проверять "destType":
class BooleanTypeConverter : BooleanConverter
{
  public override object ConvertTo(ITypeDescriptorContext context, 
    CultureInfo culture,
    object value, 
    Type destType)
  {
    return (bool)value ? 
      "Есть" : "Нет";
  }

  public override object ConvertFrom(ITypeDescriptorContext context, 
    CultureInfo culture,
    object value)
  {
    return (string)value == "Есть";
  }
}


2.

Реализовать EnumTypeConverter, осуществляющий преобразование к строке с учетом атрибута Description…

ИМХО, DiaplayName гораздо умеснее в подобной ситуации. А не сделал ли кто уже подобный класс, но который умеет работать с Flags-enum-ами? То есть где было бы реализовано ConvertFrom из локализованной строки в значение? Всегда ли правильно будет использовать Thread.CurrentThread.CurrentUICulture для выбора вариантов или культуру можено как-то выцепить из контекста?

3.
 public override void PaintValue(PaintValueEventArgs e)
  {
    // картинки хранятся в ресурсах с именами, соответствующими
    // именам каждого члена перечисления Sex
    string resourcename = ((Sex)e.Value).ToString();

    // достаем картинку из ресурсов
    Bitmap sexImage =
      (Bitmap)Resources.ResourceManager.GetObject(resourcename);
    Rectangle destRect = e.Bounds;
    sexImage.MakeTransparent();

    // и отрисовываем
    e.Graphics.DrawImage(sexImage, destRect);
  }

Не надо ли вызывать sexImage.Dispose()?

4.

Как реализовать отображение составного свойства?


При использовании этого аттрибута с написанными мною UserControl-ами, на вкладке событий PropertyGrid-а почему-то не добавляются обработчики для компонентов, показанных через "ExpandableObjectConverter" Как с этим можно справиться?
Help will always be given at Hogwarts to those who ask for it.
Re[2]: PropertyGrid FAQ
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 17.01.07 16:17
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>2.

Реализовать EnumTypeConverter, осуществляющий преобразование к строке с учетом атрибута Description…

_FR>ИМХО, DiaplayName гораздо умеснее в подобной ситуации.

слово-то покрасивше, только компилятор говорит:

error CS0592: Attribute 'DisplayName' is not valid on this declaration type. It is valid on 'class, method, property, indexer, event' declarations only.


как это разрулить?
... << RSDN@Home 1.2.0 alpha rev. 669>>
Re[3]: PropertyGrid FAQ
От: _FRED_ Черногория
Дата: 17.01.07 16:55
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

_FR>>2.

Реализовать EnumTypeConverter, осуществляющий преобразование к строке с учетом атрибута Description…

_FR>>ИМХО, DiaplayName гораздо умеснее в подобной ситуации.

OE>слово-то покрасивше, только компилятор говорит:

OE>error CS0592: Attribute 'DisplayName' is not valid on this declaration type. It is valid on 'class, method, property, indexer, event' declarations only.

OE>как это разрулить?

Дать мне по башке, иначе никак Виноват, поторопился.

В любом случае, значение надо грузить из ресурсов, поэтому:
  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Field)]
  public class LocalisedDisplayNameAttribute : DisplayNameAttribute
  {
    #region Constructors\Destructor

    public LocalisedDisplayNameAttribute(string resourceName) : base(LoadResource(resourceName)) {

    }

    #endregion Constructors\Destructor

    #region Methods

    private static string LoadResource(string resourceName) {
      return Properties.Resources.ResourceManager.GetString(resourceName);
    }

    #endregion Methods
  }

  public enum MyValues
  {
    [LocalisedDisplayName(Resources.Value1)]
    Value1,

    [LocalisedDisplayName(Resources.Value2)]
    Value2,
  }
Help will always be given at Hogwarts to those who ask for it.
Re: PropertyGrid FAQ
От: Трубаров Вячеслав Украина  
Дата: 18.01.07 00:38
Оценка:
Здравствуйте, Алексей Кирюшкин, Вы писали:

АК>Статья:

АК>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



Отличная статья.

Только вот такой вроде как простой вопрос возник (создание редакторов проблем не вызвало, а тут такая мелочь...):
PropertyGrid события не показывает, но ведь они есть в стандартном Properties окне дизайнера, который тоже отображает изменения сделанные атрибутами.
Это я к тому что такой атрибут как Category — не работает для event'ов. Это событие просто не появляется в Properties, хоть указывай атрибут, хоть не указывай. Никак нельзя сделать чтобы он показывался?


// для свойства, естесственно, работает

[Category("Category1")]
public int Position
{
  get { return position; }
  set { position = value; }
}

// а вот для события нет...

public delegate void ChangedEventHandler();

[Category("Category2")]
public ChangedEventHandler PositionChanged;


PositionChanged не появляется в Properties... Хотя он конечно доступен программно. Просто хотелось бы чтобы он был виден и через дизайнер.
Re[2]: PropertyGrid FAQ
От: _FRED_ Черногория
Дата: 18.01.07 07:27
Оценка: 10 (2)
Здравствуйте, Трубаров Вячеслав, Вы писали:

ТВ>Это я к тому что такой атрибут как Category — не работает для event'ов.


Работает.

ТВ>// а вот для события нет...
ТВ>public delegate void ChangedEventHandler();

ТВ>[Category("Category2")]
ТВ>public event ChangedEventHandler PositionChanged;


Без ключегвого свова "event": PositionChanged — лишь открытое поле.
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re: PropertyGrid и обновления свойств?
От: laad  
Дата: 18.01.07 10:50
Оценка:
кто-нибудь сталкивался с необходимостью отображения изменений (произошедших вне PropertyGrid) в гриде?
PropertyGrid, как я понял, даже не думает подписываться на изменения показываемых PropertyDescriptor — в студии, видимо,
он отслеживает события IComponentChangeService — если это так, как его туда подцепить?
Re[3]: PropertyGrid FAQ
От: Трубаров Вячеслав Украина  
Дата: 18.01.07 18:41
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Без ключегвого свова "event": PositionChanged — лишь открытое поле.


Тьфу ты, дырявая моя башка Точно, спасибо.
Re: PropertyGrid FAQ
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 19.01.07 08:08
Оценка:
АК>Статья:
PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



добавил до кучи "Как скрыть пароль при редактировании?"
... << RSDN@Home 1.2.0 alpha rev. 668>>
Re: PropertyGrid FAQ
От: acronim  
Дата: 06.02.07 09:06
Оценка:
Здравствуйте, Алексей Кирюшкин, Вы писали:

Может и оффтоп, но все же

На 1.2 в Гриде была официальная бага(не могу найти ссылку ) Проявление примерно следующее

Редакторуем класс, свойство которого массив обьектов(наример два). Обьекты имеют поля. Так вот если
1) розвернуть все плюсики, в т.ч. свойст обьектов в массиве, установить фокус на свойство обьекта в массиве (не уверен)
2) вызвать редактор массива
3) поудалять, подобавлять полей
4) закрыть редактор

Возникает "index out of bounds".

Лечилось написанием своего редактора (возможно и можно подцепить стандартный) массивов и перед выходом из UITypeEditor.EditValue сворачиванием дерева




// Принудительно обнновляем грид если редактировалась динамическая структура

PropertyGrid* m_propertyGrid =  __try_cast<GlobalizedPropertyGrid::GlobalizedObject*>(context->get_Instance())->PropGrid;
GridItem* gi = m_propertyGrid->SelectedGridItem;
GridItem* parent = NULL;
while (gi != NULL)
{
    parent = gi;
    gi = gi->Parent;
}
if (parent != NULL)
{
    GridItemCollection* coll = parent->get_GridItems();
    for(int i = 0; i < coll->Count; i++)
    {
        GridItem* child    = coll->get_Item(i);
        if (child->GridItemType == GridItemType::Category)
        {
            GridItemCollection* coll2 = child->get_GridItems();
            for(int i = 0; i < coll2->Count; i++)
            {
               coll2->get_Item(i)->Expanded = false;
            }
        }
        else
            child->Expanded = false;
    }                                                                    
}
m_propertyGrid->Refresh();


Более полный фрагмент



        // Отображает визальный диалог для редактирования<br> 
        // коллекции соответствующего типа<br>
        // Связь между редактируемым свойством и типом <br>
        // коллекции устанавливается статически в ресурсы <br>
        // программы во время разработки
        public __gc class FieldListCollectionUITypeEditor : public System::Drawing::Design::UITypeEditor 
            {
            public:
            FieldListCollectionUITypeEditor() {}
                        
            System::Drawing::Design::UITypeEditorEditStyle GetEditStyle(System::ComponentModel::ITypeDescriptorContext* context) {
                return UITypeEditorEditStyle::Modal;
            }

            // Редактирует свойство
            Object* EditValue(System::ComponentModel::ITypeDescriptorContext* context, System::IServiceProvider* provider, Object* value) {
                String* ResoursePath = S"NIST.VALUE";
                // Return the value if the value is not of type FieldBase* __gc[].
                
                // Необходимо включить проверку на входные данные
                // if (value->GetType() != __typeof(System::String)&&( value->GetType() != __typeof(System::Int32)))
                //      return value;
                String* propertyName = S"";
                if (context->get_PropertyDescriptor()!=NULL)
                {
                    propertyName = context->get_PropertyDescriptor()->get_Name();                
                }                
                //
                System::Reflection::Assembly* ass = System::Reflection::Assembly::GetEntryAssembly();
                // Now use table name and display name id to access the resources.  
                ResourceManager* rm = new ResourceManager(ResoursePath,ass);
                // Get the string from the resources.         
                System::String* n = rm->GetString(String::Concat(propertyName,S"TYPE"));
                if (n!=NULL)
                {
                    NIST::CollectionEditor* editor = new NIST::CollectionEditor();
                    
                    // инициализируем редактор                    
                    if (n->Equals(S"String"))
                    {    
                        FieldCollectionString* fc = __try_cast<FieldCollectionString*>(value);
                        //Create temp copy of colrction
                        FieldCollection* temp = new FieldCollectionString();
                        for (int i = 0; i < fc->Count; i++)
                        {
                            __try_cast<FieldCollectionString*>(temp)->Add(fc->get_Item(i));
                        }
                        editor->setSource(temp,n);
                    }
                    else if (n->Equals(S"DateTime"))
                    {
                        FieldCollectionDateTime* fc = __try_cast<FieldCollectionDateTime*>(value);
                        //Create temp copy of colrction
                        FieldCollection* temp = new FieldCollectionDateTime();
                        for (int i = 0; i < fc->Count; i++)
                        {
                            __try_cast<FieldCollectionDateTime*>(temp)->Add(fc->get_Item(i));
                        }
                        editor->setSource(temp,n);
                    }
                    else
                    {                    
                        FieldCollection* fc = __try_cast<FieldCollection*>(value);
                        //Create temp copy of colrction
                        FieldCollection* temp;
                        if (n->Equals(S"FieldDAI"))
                        {
                            temp = new FieldCollectionDAI();
                        }
                        else if (n->Equals(S"FieldCNO"))
                        {
                            temp = new FieldCollectionCNO();
                        }
                        else if (n->Equals(S"FieldORN"))
                        {
                            temp = new FieldCollectionORN();
                        }
                        else if (n->Equals(S"FieldNAM"))
                        {
                            temp = new FieldCollectionNAM();
                        }
                        else if (n->Equals(S"FieldGSA"))
                        {
                            temp = new FieldCollectionGSA();
                        }
                        else if (n->Equals(S"FieldFPR"))
                        {
                            temp = new FieldCollectionFPR();
                        }
                        else 
                            return value;

                        for (int i = 0; i < fc->Count; i++)
                        {
                            temp->Add(fc->get_Item(i));
                        }
                        editor->setSource(temp,n);                    
                    }
                    
                    // получаем результат
                    if (editor->ShowDialog()==DialogResult::OK)
                    {        
                        if (n->Equals(S"String"))
                        {    
                            value = __try_cast<FieldCollectionString*>(editor->collection);                        
                        }
                        else if (n->Equals(S"DateTime"))
                        {
                            value = __try_cast<FieldCollectionDateTime*>(editor->collection);
                        }
                        else
                            value = editor->collection;
                    }
                }
                
                // Принудительно обнновляем грид если редактировалась динамическая структура
                

                //if (context->get_Instance()->GetType() == __typeof(GlobalizedPropertyGrid::GlobalizedObject))
                {
                    PropertyGrid* m_propertyGrid =  __try_cast<GlobalizedPropertyGrid::GlobalizedObject*>(context->get_Instance())->PropGrid;
                    GridItem* gi = m_propertyGrid->SelectedGridItem;
                    GridItem* parent = NULL;
                    while (gi != NULL)
                    {
                        parent = gi;
                        gi = gi->Parent;
                    }
                    if (parent != NULL)
                    {
                        GridItemCollection* coll = parent->get_GridItems();
                        for(int i = 0; i < coll->Count; i++)
                        {
                            GridItem* child    = coll->get_Item(i);
                            if (child->GridItemType == GridItemType::Category)
                            {
                                GridItemCollection* coll2 = child->get_GridItems();
                                for(int i = 0; i < coll2->Count; i++)
                                {
                                   coll2->get_Item(i)->Expanded = false;
                                }
                            }
                            else
                                child->Expanded = false;
                        }                                                                    
                    }
                    m_propertyGrid->Refresh(); 
                }
                
                return value;
            }

            
            // Draws a representation of the property's value.
            void PaintValue(System::Drawing::Design::PaintValueEventArgs* e) {
                }

            // Indicates whether the UITypeEditor supports painting a
            // representation of a property's value.
            bool GetPaintValueSupported(System::ComponentModel::ITypeDescriptorContext* context) {
                return false;
            }
            };
Все должно быть просто
Re[2]: PropertyGrid и обновления свойств?
От: vensub Украина  
Дата: 06.02.07 09:53
Оценка:
Здравствуйте, laad, Вы писали:

L>кто-нибудь сталкивался с необходимостью отображения изменений (произошедших вне PropertyGrid) в гриде?

L>PropertyGrid, как я понял, даже не думает подписываться на изменения показываемых PropertyDescriptor — в студии, видимо,
L>он отслеживает события IComponentChangeService — если это так, как его туда подцепить?

внутри UITypeEditor что-то вроде:

IComponentChangeService ccs = provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
ccs.OnComponentChanged(..);
Re[3]: PropertyGrid и обновления свойств?
От: laad  
Дата: 06.02.07 10:59
Оценка:
Здравствуйте, vensub, Вы писали:

V>Здравствуйте, laad, Вы писали:


L>>кто-нибудь сталкивался с необходимостью отображения изменений (произошедших вне PropertyGrid) в гриде?

L>>PropertyGrid, как я понял, даже не думает подписываться на изменения показываемых PropertyDescriptor — в студии, видимо,
L>>он отслеживает события IComponentChangeService — если это так, как его туда подцепить?

V>внутри UITypeEditor что-то вроде:


V>
V>IComponentChangeService ccs = provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
V>ccs.OnComponentChanged(..);
V>


Спасибо Ж)
на самом деле, там несколько тоньше: нужно установить PropertyGrid.Site такой, чтобы он отвечал на GetService( typeof( IDesignerHost) )
только в таком случае PropertyGrid начинает запрашивать другие сервисы, в том числе IComponentChangeService.

Вообще говоря, похоже на некоторую нестыковку у микрософта — с одной стороны, PropertyDescriptor поддерживает в принципе оповещения об изменении значения, с другой — PropertyGrid на него забивает и использует сервис. Похоже, в ходе разработки поняли, что нужны транзакции для нормальной скорости работы всех связки — и сделали IComponentChangeService.
Re: PropertyGrid FAQ
От: Аноним  
Дата: 06.02.07 16:52
Оценка:
Здравствуйте, Алексей Кирюшкин, Вы писали:

АК>Статья:

АК>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



Спасибо за статью.

Есть вопрос по editor-ам.
Есть тип MyCollectionEditor, производный от CollectionEditor.

Конструктор CollectionEditor выглядит так:

public CollectionEditor (Type collection_type)


Мне же нужно, чтобы конструктор моего класса MyCollectionEditor, принимал
помимо типа коллекции, ещё некоторые другие параметры, т.е. чтобы мой конструктор
выглядел вот так:

public MyCollectionEditor (Type collection_type, SomeType additional_data)


Так вот, возможно ли как-то прикрутить мой MyCollectionEditor к редактированию коллекции
в PropertyGrid?
Re: PropertyGrid FAQ
От: D.Triton Украина  
Дата: 06.02.07 19:29
Оценка:
Здравствуйте, Алексей Кирюшкин, Вы писали:

АК>Статья:

АК>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



АК>Авторы:

АК> Алексей Кирюшкин


Отличная статья, огромное спасибо.
Но у меня есть одна проблема.


Мне нужно сделать редактирование поля из БД.


пусть я должен хранить идентификатор сущности в БД, а показывать значение соотв. поля этому идентификатору.

К примеру, я храню идентификатор сущьности "Еденица измерения", а в поле PropertyGrid вместо цифрового идентификатора показывается его наименование.


У меня получилось это отчасти.

Показать имя по идентификатору.
Но как только мне понадобилось
вызывать соотв. форму выбора еденицы измерения (поле PropertyGrid редактируется только через соотв. модальное окно выбора ед. измерения) у меня ничего не получилось.


Прошу прощения за каламбур.


Итак есть класс Unit


public class Unit
{
private decimal unitId;


public decimal UnitId
{
   get{return unitId;}
   set{unitId = value;}
}
}



после того как я подсуну этот класс в PropertyGrid.SelectedObject, я хочу видеть в
отображаемом поле не Id, а наименование идентификатора.

Выбор Unit у меня происходит из отдельной формы. Ее вызов я делаю реализацией своего EditAttribute.

Но для преобразования Id в наименование я использовал потомка от DecimalConverter. Но ничего не получилось, когда я стал использовать и Editor и TypeConverter.
Результат — отображение только идентификатора.
Когда я комментил Editor, то все работало, но я не мог тогда использовать свою модальную форму для выбора единицы измерения.

Люди добрые помогите, или подскажите, что читать. У меня уже истерика начинается.

Большое всем спасибо
Re[2]: PropertyGrid FAQ
От: D.Triton Украина  
Дата: 07.02.07 10:22
Оценка:
Здравствуйте, D.Triton, Вы писали:


DT>Мне нужно сделать редактирование поля из БД.



DT>пусть я должен хранить идентификатор сущности в БД, а показывать значение соотв. поля этому идентификатору.



Решение очень простое.

Делается класс, который хранит как идентификатор, так и строковое представление (наименование сущности).


public class YearRequestByMonthConfig : BaseReportConfig
    {
        public class EntityHolder
        {
            public EntityHolder()
            {
            }

            public EntityHolder(decimal id, string name)
            {
                this.id = id;
                this.name = name;
            }

            public decimal Id
            {
                get { return id; }
                set { id = value; }
            }

            private decimal id;

            public string Name
            {
                get { return name; }
                set { name = value; }
            }
           
            public override string ToString()
            {
                return Name;
            }

            private string name;
        }


Далее при реализации выбора сущности из БД делаем чего-то такое:
internal class DepartmentSelectEditor : UITypeEditor
        {
            public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
            {
                return UITypeEditorEditStyle.Modal;
            }

            private object value;


            /// <summary>
            /// Реализация метода редактирования
            /// </summary>
            public override Object EditValue(
                ITypeDescriptorContext context,
                IServiceProvider provider,
                Object value)
            {
                this.value = value;
                if ((provider != null) &&
                    (((IWindowsFormsEditorService) provider.GetService(typeof (IWindowsFormsEditorService))) != null))
                {
                    IDepartmentExplorerPresenter dex = BLHelper.GetDepartmentExplorerPresenter();
                    dex.DepartmentSelect +=
                        delegate(object sender, DepartmentExplorerSelectionEventArgs args)
                            {
                                string name = DataProviderHelper.EnterpriseDAL.GetEnterpriseName(args.EnterpriseId);
                                this.value = new EntityHolder(args.EnterpriseId, name);
                            };

                    dex.ShowDepartmentExplorer();
                }
                value = this.value;
                this.value = null;
                return value;
            }
        }



А пол, которое редактируем (скажем какое-то подразделение)

отображаем так:

        [Browsable(true)]
        [DisplayNameLocalized(typeof (YearRequestByMonthRptConfigResources), "Department")]        
        [Editor(typeof (DepartmentSelectEditor), typeof (UITypeEditor))]        
            public EntityHolder Department
        {
            get { return department; }
            set { department = value; }
        }



Все работает просто супер

Всем спасибо.
Re: PropertyGrid FAQ
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 18.02.07 14:14
Оценка:
добавлено: "Как избавиться от ошибки “Конструктор для типа "System.String" не найден” при редактировании свойств типа StringCollection?"
... << RSDN@Home 1.2.0 alpha rev. 675>>
Re: PropertyGrid FAQ
От: weakfish  
Дата: 21.02.07 15:17
Оценка:
Здравствуйте, Алексей Кирюшкин, Вы писали:

АК>Статья:

АК>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



Приветствую.
Есть непонятка с локализацией. Т.е., например, задан [DisplayName("Адрес сервера")], а надо что бы текст, отображаемый в PropertyGrid, был в соответствии с текущей локалью без внесений изменений в код. Решение нашёл в следующей статье — http://rsdn.ru/article/dotnet/dnetappcfg.xml
Автор(ы): Андрей Корявченко
Дата: 12.05.2003
Не секрет, что практически каждое приложение требует каких-то настроек. Данная статья рассказывает об одном из возможных способов реализации механизма их хранения и редактирования. Исходные коды взяты из реального приложения, RSDN@Home, оффлайн-клиента для форумов www.rsdn.ru.
— т.е. в атрибуте DisplayName задаю имя строки в ресурсном файле, а во врапере для неё получаю значение из файлов ресурсов требуемой локали. Только при этом, пока не разобрался почему, не работает приведённый в данной статье метод сортировки при помощи атрибута PropertyOrder . Подозреваю, вернее даже почти уверен, что у меня во врапере какая-то недоработка, которую в ближайшее время найду, но если у автора статьи (или может кто ещё решал этот вопрос) есть варианты решения проблемы локализации, то было бы интересно ознакомится.
Re[2]: PropertyGrid FAQ
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 21.02.07 15:37
Оценка: :)
Здравствуйте, weakfish, Вы писали:

W>(или может кто ещё решал этот вопрос) есть варианты решения проблемы локализации, то было бы интересно ознакомится.


Re[2]: PropertyGrid FAQ
Автор: D.Triton
Дата: 17.01.07
... << RSDN@Home 1.2.0 alpha rev. 675>>
Re[3]: PropertyGrid FAQ
От: weakfish  
Дата: 22.02.07 08:20
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, weakfish, Вы писали:


W>>(или может кто ещё решал этот вопрос) есть варианты решения проблемы локализации, то было бы интересно ознакомится.


OE>Re[2]: PropertyGrid FAQ
Автор: D.Triton
Дата: 17.01.07


Для локализации свойств (DisplayNameAttribute) и описаний (DescriptionAttribute) этот вариант подходит, а с CategoryAttribute не получается, потому как у него нет свойства CategoryValue, а строка Category доступна только на чтение .
Re[4]: PropertyGrid FAQ
От: weakfish  
Дата: 22.02.07 08:24
Оценка:
Здравствуйте, weakfish, Вы писали:

W>Здравствуйте, Odi$$ey, Вы писали:


OE>>Здравствуйте, weakfish, Вы писали:


W>>>(или может кто ещё решал этот вопрос) есть варианты решения проблемы локализации, то было бы интересно ознакомится.


OE>>Re[2]: PropertyGrid FAQ
Автор: D.Triton
Дата: 17.01.07


W>Для локализации свойств (DisplayNameAttribute) и описаний (DescriptionAttribute) этот вариант подходит, а с CategoryAttribute не получается, потому как у него нет свойства CategoryValue, а строка Category доступна только на чтение .


А, точно, не подумал, что можно через базовый конструктор, сделал через — public CategoryLocAttribute(string resId) : base(rm.GetString(resId)) — работает.
Re: PropertyGrid FAQ
От: OldHand Россия  
Дата: 15.03.07 14:55
Оценка:
Здравствуйте, Алексей Кирюшкин, Вы писали:

АК>Статья:

АК>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



Попытка использовать EnumTypeConverter в секции конфигурации
  public class MySectionConfiguration : ConfigurationSection
  {
        //...

    [ConfigurationProperty("sex")]
    [DisplayName("Пол")]
    [Description("Пол")]
    [Category("2. Общие")]
    [TypeConverter(typeof(EnumTypeConverter))]
    public SEX Sex
    {
      get { return (SEX)this["sex"]; }
      set { this["sex"] = value; }
    }
        //...
  }

  cfg.Sex = SEX.Unknown;

Вызывает MissingMethodException с сообщением:
"Для данного объекта не определено беспараметрических конструкторов."

Можно излечить?
--
PS: Visual Studio 2005 Ver. 8.0.50727.42
Re: PropertyGrid FAQ
От: muradm Россия  
Дата: 21.03.07 15:18
Оценка:
Очень полезная статья!

Но есть один вопрос:
Делаю всплывающий список, в котором выбираю строковые значения для свойства (через TypeConverter). Значения беру из базы. Но со строками работать не очень хорошо в моем случае. Хочется, чтобы пользователь выбирал строковые значения, но свойству присваивался соотетствующий ID строки. То есть подгружать из базы пары ID + Text. А при выборе свойству присваивать ID.

Есть ли выход?
Re[2]: PropertyGrid FAQ
От: _FRED_ Черногория
Дата: 21.03.07 16:17
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Мне же нужно, чтобы конструктор моего класса MyCollectionEditor, принимал

А>помимо типа коллекции, ещё некоторые другие параметры…

Откуда эти данные могут браться? Например, можно переопределить ICustomTypeDescriptor.GetEditor
... << RSDN@Home 1.2.0 alpha rev. 675>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re: PropertyGrid FAQ
От: ZeeM  
Дата: 22.03.07 13:10
Оценка:
В данной статье освещается вопрос — Как управлять видимостью свойства в зависимости от значения другого свойства?


Каким образом можно реализовать, чтобы видимость одного свойства зависела от значения ДРУГИХ СВОЙСТВ(не одного, а нескольких).

Спасибо
Re[2]: PropertyGrid FAQ
От: burkut_vit  
Дата: 17.07.07 09:48
Оценка:
Фак суперский вот только возник маленький вопросик. Как сделать так чтобы выпадающий список закрывался не только по нажатию интера но и при клике мышью.
Мне понадобилось воткнуть listbox теперь думаю как его красиво закрыть после выбора, а в факе нет исходника класса ForeignLangsControl что бы посмотреть что там делается по нажатию кнопочки.
Re[3]: PropertyGrid FAQ
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 17.07.07 11:46
Оценка:
Здравствуйте, burkut_vit, Вы писали:

_>а в факе нет исходника класса ForeignLangsControl что бы посмотреть что там делается по нажатию кнопочки.


он там есть, в приложенном проекте
... << RSDN@Home 1.2.0 alpha rev. 694>>
Re[4]: PropertyGrid FAQ
От: burkut_vit  
Дата: 18.07.07 04:15
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, burkut_vit, Вы писали:


_>>а в факе нет исходника класса ForeignLangsControl что бы посмотреть что там делается по нажатию кнопочки.


OE>он там есть, в приложенном проекте

И правда есть. Извиняюсь за невнимательность. . Все заработало, спасибо.
Re: PropertyGrid FAQ
От: Аноним  
Дата: 18.07.07 05:46
Оценка:
Доброго времени суток.
А можно ли управлять шириной выпадающего списка(контрола), а то текст не видно?
Re: PropertyGrid FAQ
От: Аноним  
Дата: 15.10.07 14:34
Оценка:
Здравствуйте, Алексей Кирюшкин, Вы писали:

АК>Статья:

АК>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



АК>Авторы:

АК> Алексей Кирюшкин

АК>Аннотация:

АК>Как заменить имя переменной в левой колонке “человеческим” именем свойства?
АК>Как отобразить расширенную подсказку по свойству в нижнем окне?
АК>Как сгруппировать свойства по категориям?
АК>Как отобразить свойство, недоступное для редактирования?
АК>Как заменить стандартные True/False в отображении свойств типа bool?
АК>Как заменить стандартное отображение имен членов перечисления?
АК>Как показать свою картинку для каждого значения из перечисления?
АК>Как организовать выбор значения из выпадающего списка, формируемого программно?
АК>Как реализовать отображение составного свойства?
АК>Как организовать выбор файла с заданным расширением?
АК>Как организовать редактирование свойства в собственной форме?
АК>Как организовать редактирование свойства в выпадающем списке?
АК>Как управлять видимостью свойства в зависимости от значения другого свойства?
АК>Как избавиться от стандартного “(Collection)” в правой колонке для свойств-коллекций?
АК>Как заменить стандартные подписи (Members, properties) в окне Collection Editor?
АК>Как добавить в Collection Editor окно с расширенной подсказкой по редактируемым свойствам?
АК>Как задать отличный от алфавитного порядок следования свойств внутри категории?
АК>Как запомнить и восстановить положение разделителя колонок в PropertyGrid?

а есть ли где нибудь вариант того как сделать это в managed c++ ???
пытался сам переделать, но все равно осталась куча ошибок, к которым без понятия с какого боку подходить. Может кто тоже уже пытался это сделать?
Re[2]: PropertyGrid FAQ
От: Аноним  
Дата: 16.10.07 08:18
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Алексей Кирюшкин, Вы писали:


АК>>Статья:

АК>>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



АК>>Авторы:

АК>> Алексей Кирюшкин

АК>>Аннотация:

АК>>Как заменить имя переменной в левой колонке “человеческим” именем свойства?
АК>>Как отобразить расширенную подсказку по свойству в нижнем окне?
АК>>Как сгруппировать свойства по категориям?
АК>>Как отобразить свойство, недоступное для редактирования?
АК>>Как заменить стандартные True/False в отображении свойств типа bool?
АК>>Как заменить стандартное отображение имен членов перечисления?
АК>>Как показать свою картинку для каждого значения из перечисления?
АК>>Как организовать выбор значения из выпадающего списка, формируемого программно?
АК>>Как реализовать отображение составного свойства?
АК>>Как организовать выбор файла с заданным расширением?
АК>>Как организовать редактирование свойства в собственной форме?
АК>>Как организовать редактирование свойства в выпадающем списке?
АК>>Как управлять видимостью свойства в зависимости от значения другого свойства?
АК>>Как избавиться от стандартного “(Collection)” в правой колонке для свойств-коллекций?
АК>>Как заменить стандартные подписи (Members, properties) в окне Collection Editor?
АК>>Как добавить в Collection Editor окно с расширенной подсказкой по редактируемым свойствам?
АК>>Как задать отличный от алфавитного порядок следования свойств внутри категории?
АК>>Как запомнить и восстановить положение разделителя колонок в PropertyGrid?

А>а есть ли где нибудь вариант того как сделать это в managed c++ ???

А>пытался сам переделать, но все равно осталась куча ошибок, к которым без понятия с какого боку подходить. Может кто тоже уже пытался это сделать?

конкретно интересует вопрос "Как управлять видимостью свойства в зависимости от значения другого свойства?"
Re[3]: PropertyGrid FAQ
От: _FRED_ Черногория
Дата: 16.10.07 10:10
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>конкретно интересует вопрос "Как управлять видимостью свойства в зависимости от значения другого свойства?"


Лучше посмотреть здесь
Автор: _FRED_
Дата: 28.03.07
(Этот способ, например. избавлен от указанного в статье недостатка).

В чём именно сложности в переносе кода на MC++?
... << RSDN@Home 1.2.0 alpha rev. 717>>
Help will always be given at Hogwarts to those who ask for it.
Re: PropertyGrid FAQ
От: Владимир Л.  
Дата: 16.10.07 11:02
Оценка:
Здравствуйте, Алексей Кирюшкин.

Спасибо за статью.

У меня вопрос, который уже задавался в этом и других форумах, но ответа я нигде не видел.

Есть ли фозможность менять цвет, фонт у отдельных строк PropertyGrid?

Например, некоторые свойства пользователь должен поменять, они пусть будут синие.
Некоторые — трогать нежелательно (но можно), пусть будут серыми и т.п.

Удачи!
Re: PropertyGrid FAQ
От: vap  
Дата: 04.03.08 09:47
Оценка:
Здравствуйте, Алексей Кирюшкин, Вы писали:

АК>Статья:

АК>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



спасибо огромное за статью!
но, у меня возник, надеюсь интересный, вопрос.
мне нужно показывать и менять значения даты и времени в PropertyGrid. к обработке даты претензий не имею — автоматически вызывается DateTimeEditor. а вот как мне заставить этот эдитор показывать и редактировать время?
я это вижу примерно так: где-то нужно задать CustomFormat для отображения времени, убрать стандартный редактор даты + повесить кнопочки up/down, но я незнаю где и как это все задается.
заранее спасибо.
Re[2]: PropertyGrid FAQ
От: vehfl  
Дата: 06.03.08 07:10
Оценка:
Здравствуйте, ZeeM, Вы писали:

ZM>В данной статье освещается вопрос — Как управлять видимостью свойства в зависимости от значения другого свойства?



ZM>Каким образом можно реализовать, чтобы видимость одного свойства зависела от значения ДРУГИХ СВОЙСТВ(не одного, а нескольких).


ZM>Спасибо


Актуальный и для меня вопрос.
Никто его не может подсказать?
Re[3]: PropertyGrid FAQ
От: _FRED_ Черногория
Дата: 06.03.08 07:54
Оценка:
Здравствуйте, vehfl, Вы писали:

ZM>>В данной статье освещается вопрос — Как управлять видимостью свойства в зависимости от значения другого свойства?

ZM>>Каким образом можно реализовать, чтобы видимость одного свойства зависела от значения ДРУГИХ СВОЙСТВ(не одного, а нескольких).
V>Актуальный и для меня вопрос.
V>Никто его не может подсказать?

[C# 2.0] Динамическое управление набором свойств
Автор: _FRED_
Дата: 28.03.07
Help will always be given at Hogwarts to those who ask for it.
Re[4]: PropertyGrid FAQ
От: vehfl  
Дата: 13.03.08 11:04
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, vehfl, Вы писали:


ZM>>>В данной статье освещается вопрос — Как управлять видимостью свойства в зависимости от значения другого свойства?

ZM>>>Каким образом можно реализовать, чтобы видимость одного свойства зависела от значения ДРУГИХ СВОЙСТВ(не одного, а нескольких).
V>>Актуальный и для меня вопрос.
V>>Никто его не может подсказать?

_FR>[C# 2.0] Динамическое управление набором свойств
Автор: _FRED_
Дата: 28.03.07


а не могли бы Вы выслать исходные коды на [chandif собака gmail точка com]
Re[5]: PropertyGrid FAQ
От: _FRED_ Черногория
Дата: 13.03.08 13:04
Оценка:
Здравствуйте, vehfl, Вы писали:

_FR>>[C# 2.0] Динамическое управление набором свойств
Автор: _FRED_
Дата: 28.03.07


V>а не могли бы Вы выслать исходные коды на [chandif собака gmail точка com]


Всё необходимое в посте есть В чём сложности?
Help will always be given at Hogwarts to those who ask for it.
Re[6]: PropertyGrid FAQ
От: vehfl  
Дата: 31.03.08 07:20
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, vehfl, Вы писали:


_FR>>>[C# 2.0] Динамическое управление набором свойств
Автор: _FRED_
Дата: 28.03.07


V>>а не могли бы Вы выслать исходные коды на [chandif собака gmail точка com]


_FR>Всё необходимое в посте есть В чём сложности?


лень, было соображалку включать, но спасибо разобрался)))...
такой вопрос, а как можно для своего класса два различных TypeConvertera ?
те я хочу получить что то типа

[TypeConverter(typeof(PropertySorter))] -- для управления сортировкой
[TypeConverter(typeof(ComponentTypeConverter))] -- для управления видимостью и редактированием
public class MyClass : Component
{
...
}

public class ComponentTypeConverter : CustomPropertiesTypeConverter<MyClass>
{
...
}

class PropertySorter : ExpandableObjectConverter
Re[7]: PropertyGrid FAQ
От: _FRED_ Черногория
Дата: 31.03.08 08:57
Оценка:
Здравствуйте, vehfl, Вы писали:

V>такой вопрос, а как можно для своего класса два различных TypeConvertera ?


И какой из двух должен будет быть создан при таком вот вызове:
var converter = TypeConverter.GetConverter(typeof(MyClass));

?
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[8]: PropertyGrid FAQ
От: vehfl  
Дата: 31.03.08 09:55
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, vehfl, Вы писали:


V>>такой вопрос, а как можно для своего класса два различных TypeConvertera ?


_FR>И какой из двух должен будет быть создан при таком вот вызове:

_FR>
_FR>var converter = TypeConverter.GetConverter(typeof(MyClass));
_FR>

_FR>?

что то я не совсем понял((...
подозреваю что какой вопрос такой и ответ

пояснения чего я хочу получить в итоге:
если коротко хочется чтобы мой класс обладал возможностью указания сортировки полей посредством задания атрибута TypeConverter с параметром PropertySorter, а также возможностью регулировки видимости и возможностью редактирования полей согласно описанному вами примеру

в данный момент я не совсем понимаю как это я могу сделать((
так как, когда пишу

    [TypeConverter(typeof(ComponentTypeConverter))]
    [TypeConverter(typeof(PropertySorter))]
    public class MyClass

или

    [TypeConverter(typeof(ComponentTypeConverter), (typeof(PropertySorter))]
    public class MyClass


получаю сообщения об ошибке
Re[9]: PropertyGrid FAQ
От: _FRED_ Черногория
Дата: 31.03.08 10:28
Оценка:
Здравствуйте, vehfl, Вы писали:

V>пояснения чего я хочу получить в итоге:


Это понятно. Я пытался показать, почему подобное невозможно. У типа может быть только один конвертер (в данный момент времени), поэтому надо либо в одном конверторе реализовать всю необходимую функциональность, либо поиграть с ICustomTypeDescriptor-ом, что бы в зависимости от ситуации он возвращал тот или иной конвертер.
... << RSDN@Home 1.2.0 alpha 4 rev. 1048>>
Help will always be given at Hogwarts to those who ask for it.
Re[10]: PropertyGrid FAQ
От: vehfl  
Дата: 31.03.08 10:50
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, vehfl, Вы писали:


V>>пояснения чего я хочу получить в итоге:


_FR>Это понятно. Я пытался показать, почему подобное невозможно. У типа может быть только один конвертер (в данный момент времени), поэтому надо либо в одном конверторе реализовать всю необходимую функциональность, либо поиграть с ICustomTypeDescriptor-ом, что бы в зависимости от ситуации он возвращал тот или иной конвертер.


понятно...
но это какое то странное ограничение... либо реализовано как то не так )
потому что я реализовал то, что мне нужно следующим образом:
    [TypeConverter(typeof(PropertySorter))]
    public class MyClass

    ...
  
    [TypeConverter(typeof(ComponentTypeConverter))]
    public class MyClassChild : MyClass

в итоге атрибуты в MyClassChild сортируются согласно PropertySorter, и я могу регулировать видимость и редактируемость атрибутов посредством ComponentTypeConverter
Re[11]: PropertyGrid FAQ
От: vehfl  
Дата: 31.03.08 10:54
Оценка:
Здравствуйте, vehfl, Вы писали:

V>в итоге атрибуты в MyClassChild сортируются согласно PropertySorter, и я могу регулировать видимость и редактируемость атрибутов посредством ComponentTypeConverter


упс... поторопился... PropertySorter пропадает((
Re[2]: PropertyGrid FAQ
От: nikulin_andrey Великобритания  
Дата: 14.04.08 14:51
Оценка:
Здравствуйте, Владимир Л., Вы писали:

ВЛ>Есть ли фозможность менять цвет, фонт у отдельных строк PropertyGrid?

ВЛ>Например, некоторые свойства пользователь должен поменять, они пусть будут синие.
ВЛ>Некоторые — трогать нежелательно (но можно), пусть будут серыми и т.п.


Тоже интересует данный вопрос!
Re: PropertyGrid FAQ
От: Andy77 Ниоткуда  
Дата: 05.06.08 20:38
Оценка:
Спасибо за статью. А никто не подскажет, можно ли перехватить управление в момент, когда PropertyGrid только собирается вызвать SetValue у соответствующего дескриптора? Есть событие PropertyValueChanged, но, к сожалению, PropertyValueChanging отсутствует Покопался Рефлектором в кишках, ничего интересного не нашел
Re: PropertyGrid FAQ
От: Cyberdrill Россия  
Дата: 18.07.08 06:34
Оценка:
Здравствуйте,

Есть ли решение для форматирования отображаемых в гриде строк?
например, требуется отобразить значение типа double, с применением строки форматирования "F2"...
Re: PropertyGrid FAQ
От: SP_ Украина  
Дата: 26.08.08 17:06
Оценка:
Здравствуйте, Алексей Кирюшкин, Вы писали:

АК>Статья:

АК>PropertyGrid FAQ
Автор(ы): Алексей Кирюшкин
Дата: 06.12.2006
В данном FAQ собраны ответы на некоторые вопросы, возникающие при первом применении PropertyGrid.



АК>Аннотация:

АК>Как управлять видимостью свойства в зависимости от значения другого свойства?
Пытался прикрутить к кастомному WWF Activity. Вылезли следующие баги.
1.
Код Activity

    [Serializable]
    public enum TestEnum
    {
        Value1,
        Value2
    }

    [Serializable]
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class C1
    {
        private string s1 = "", s2 = "";
        public string S1
        {
            get { return s1; }
            set { s1 = value; }
        }
        public string S2
        {
            get { return s2; }
            set { s2 = value; }
        }
    }

    [Serializable]
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class C2
    {
        private int n1 = 0, n2 = 0;
        public int N1
        {
            get { return n1; }
            set { n1 = value; }
        }
        public int N2
        {
            get { return n2; }
            set { n2 = value; }
        }
    }

    public partial class Activity1 : Activity, ICustomTypeDescriptor

    {
        public Activity1()
        {
            InitializeComponent();
            Param1 = new C1();
            Param2 = new C2();
        }

        public static DependencyProperty ZZEnumValueProperty =
            DependencyProperty.Register("ZZEnumValue", typeof(TestEnum), typeof(Activity1));

        [TypeConverter(typeof(EnumTypeConverter))]
        public TestEnum ZZEnumValue
        {
            get
            {
                return ((TestEnum)(GetValue(ZZEnumValueProperty)));
            }
            set
            {
                SetValue(ZZEnumValueProperty, value);
            }
        }

        public static DependencyProperty Param1Property =
            DependencyProperty.Register("Param1", typeof(C1), typeof(Activity1));
        [DynamicPropertyFilter("ZZEnumValue", "Value1")]
        public C1 Param1
        {
            get
            {
                
                return ((C1)(GetValue(Param1Property)));
            }
            set
            {
                SetValue(Param1Property, value);
            }
        }

        public static DependencyProperty Param2Property =
            DependencyProperty.Register("Param2", typeof(C2), typeof(Activity1));
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [DynamicPropertyFilter("ZZEnumValue", "Value2")]
        public C2 Param2
        {
            get
            {
                return ((C2)(GetValue(Param2Property)));
            }
            set
            {
                SetValue(Param2Property, value);
            }
        }
        #region ICustomTypeDescriptor Members
        private PropertyDescriptorCollection GetFilteredProperties(Attribute[] attributes)
        {
            PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(this, attributes, true);
            PropertyDescriptorCollection finalProps = 
                new PropertyDescriptorCollection(new PropertyDescriptor[0]);
            foreach (PropertyDescriptor pd in pdc)
            {
                bool include = false;
                bool dynamic = false;
                foreach (Attribute a in pd.Attributes)
                {
                    DynamicPropertyFilterAttribute dpf = a as DynamicPropertyFilterAttribute;
                    if (dpf != null)
                    {
                        dynamic = true;
                        PropertyDescriptor temp = pdc[dpf.PropertyName];
                        if (dpf.ShowOn.IndexOf(temp.GetValue(this).ToString()) > -1)
                        {
                            include = true;
                        }
                    }
                }
                if (!dynamic || include)
                {
                    finalProps.Add(pd);
                }
            }
            return finalProps;
        }

        public AttributeCollection GetAttributes()
        {
            return TypeDescriptor.GetAttributes(this, true);
        }

        public string GetClassName()
        {
            return TypeDescriptor.GetClassName(this, true);
        }

        public string GetComponentName()
        {
            return TypeDescriptor.GetComponentName(this, true);
        }

        public TypeConverter GetConverter()
        {
            return TypeDescriptor.GetConverter(this, true);
        }

        public EventDescriptor GetDefaultEvent()
        {
            return TypeDescriptor.GetDefaultEvent(this, true);
        }

        public PropertyDescriptor GetDefaultProperty()
        {
            return TypeDescriptor.GetDefaultProperty(this, true);
        }

        public object GetEditor(Type editorBaseType)
        {
            return TypeDescriptor.GetEditor(this, editorBaseType, true);
        }

        public EventDescriptorCollection GetEvents(Attribute[] attributes)
        {
            return TypeDescriptor.GetEvents(this, attributes, true);
        }

        public EventDescriptorCollection GetEvents()
        {
            return TypeDescriptor.GetEvents(this, true);
        }

        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            return GetFilteredProperties(attributes);
        }

        public PropertyDescriptorCollection GetProperties()
        {
            return GetFilteredProperties(new Attribute[0]);
        }

        public object GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }

        #endregion
    }

Компилруем, добавляем в проект workflow. Кидаем на нее это самое Activity.
Устанавливаем ZZEnumValue в Value2 и соответвенно устанавливаем атрибуты Param2 в какие-нить значения.
Закрываем дизайнер Workflow.
Открываем дизайнер Workflow.
Получаем исключение:

Error Loading Workflow .... The type Activity1 has no property named Param2

Смотрим Workflow.Designer.cs
        private void InitializeComponent()
        {
            this.CanModifyActivities = true;
            ActivityLibrary1.C2 c21 = new ActivityLibrary1.C2();
            this.activity11 = new ActivityLibrary1.Activity1();
            // 
            // activity11
            // 
            this.activity11.Name = "activity11";
            c21.N1 = 23;
            c21.N2 = 44;
            this.activity11.Param2 = c21;
            this.activity11.ZZEnumValue = ActivityLibrary1.TestEnum.Value2;
            // 
            // Workflow1
            // 
            this.Activities.Add(this.activity11);
            this.Name = "Workflow1";
            this.CanModifyActivities = false;

        }

Проблема в выделенной строке. До присваивания ZZEnumValue значения Value2 свойство Param2 дизайнер не видит. Скорей всего потому что мы его вручную скрыли. Если вручную переместить выделенную строку выше
this.activity11.Param2 = c21;

или же переименовать ZZEnumValue в AAEnumValue(т.к. присваитваются свойства по алфавиту, и соотвественно значение AAEnumValue будет присвоено первым)
то все заработает.
Вообще интересно бы до причин докопаться.
2.
Если имеем в Activity "управляющее" свойство типа
    public enum TestEnum
    {
        GetValue,
        GetValuesCount,
                GetValuesList
        }

и соотвественно несколько "управляемых" по значениям этого enum, то реализация метода GetFilteredProperties будет сбоить:

if (dpf.ShowOn.IndexOf(temp.GetValue(this).ToString()) > -1)

свойство "управляемое" значением GetValue будет показываться всегда.
В общем я переписал так:

        private PropertyDescriptorCollection GetFilteredProperties(Attribute[] attributes)
        {
            PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(this, attributes, true);
            PropertyDescriptorCollection finalProps = 
                new PropertyDescriptorCollection(new PropertyDescriptor[0]);
            foreach (PropertyDescriptor pd in pdc)
            {
                bool include = false;
                bool dynamic = false;
                foreach (Attribute a in pd.Attributes)
                {
                    DynamicPropertyFilterAttribute dpf = a as DynamicPropertyFilterAttribute;
                    if (dpf != null)
                    {
                        dynamic = true;
                        PropertyDescriptor temp = pdc[dpf.PropertyName];
                        string[] values = dpf.ShowOn.Split(',');
                        string currentValue = temp.GetValue(this).ToString();
                        foreach (string avalue in values)
                        {
                            if (avalue.Trim()==currentValue)
                            {
                                include = true;
                                break;
                            }
                        }
                        break;
                    }
                }
                if (!dynamic || include)
                {
                    finalProps.Add(pd);
                }
            }
            return finalProps;
        }
Re: PropertyGrid FAQ
От: xakpc Россия linkedin.com/in/xakpc
Дата: 03.04.09 14:11
Оценка:
А как можно выяснить тип выбранного свойства?
Re[2]: PropertyGrid FAQ
От: xakpc Россия linkedin.com/in/xakpc
Дата: 06.04.09 09:16
Оценка:
Я делаю вот так
selectedGridValue.GetType().ToString().Equals("System.Single")

но мне кажется это не слишком оптимально.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.