Аннотация:
Как заменить имя переменной в левой колонке “человеческим” именем свойства?
Как отобразить расширенную подсказку по свойству в нижнем окне?
Как сгруппировать свойства по категориям?
Как отобразить свойство, недоступное для редактирования?
Как заменить стандартные True/False в отображении свойств типа bool?
Как заменить стандартное отображение имен членов перечисления?
Как показать свою картинку для каждого значения из перечисления?
Как организовать выбор значения из выпадающего списка, формируемого программно?
Как реализовать отображение составного свойства?
Как организовать выбор файла с заданным расширением?
Как организовать редактирование свойства в собственной форме?
Как организовать редактирование свойства в выпадающем списке?
Как управлять видимостью свойства в зависимости от значения другого свойства?
Как избавиться от стандартного “(Collection)” в правой колонке для свойств-коллекций?
Как заменить стандартные подписи (Members, properties) в окне Collection Editor?
Как добавить в Collection Editor окно с расширенной подсказкой по редактируемым свойствам?
Как задать отличный от алфавитного порядок следования свойств внутри категории?
Как запомнить и восстановить положение разделителя колонок в 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; }
}
}
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)
{
// картинки хранятся в ресурсах с именами, соответствующими
// именам каждого члена перечисления Sexstring 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.
Реализовать 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.
Реализовать 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>как это разрулить?
Дать мне по башке, иначе никак Виноват, поторопился.
В любом случае, значение надо грузить из ресурсов, поэтому:
Только вот такой вроде как простой вопрос возник (создание редакторов проблем не вызвало, а тут такая мелочь...):
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... Хотя он конечно доступен программно. Просто хотелось бы чтобы он был виден и через дизайнер.
Здравствуйте, Трубаров Вячеслав, Вы писали:
ТВ>Это я к тому что такой атрибут как Category — не работает для event'ов.
Работает.
ТВ>// а вот для события нет...
ТВ>public delegate void ChangedEventHandler();
ТВ>[Category("Category2")]
ТВ>publicevent 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.
кто-нибудь сталкивался с необходимостью отображения изменений (произошедших вне PropertyGrid) в гриде?
PropertyGrid, как я понял, даже не думает подписываться на изменения показываемых PropertyDescriptor — в студии, видимо,
он отслеживает события IComponentChangeService — если это так, как его туда подцепить?
На 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;
}
};
Здравствуйте, laad, Вы писали:
L>кто-нибудь сталкивался с необходимостью отображения изменений (произошедших вне PropertyGrid) в гриде? L>PropertyGrid, как я понял, даже не думает подписываться на изменения показываемых PropertyDescriptor — в студии, видимо, L>он отслеживает события IComponentChangeService — если это так, как его туда подцепить?
внутри UITypeEditor что-то вроде:
IComponentChangeService ccs = provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
ccs.OnComponentChanged(..);
Здравствуйте, 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
Есть вопрос по editor-ам.
Есть тип MyCollectionEditor, производный от CollectionEditor.
Конструктор CollectionEditor выглядит так:
public CollectionEditor (Type collection_type)
Мне же нужно, чтобы конструктор моего класса MyCollectionEditor, принимал
помимо типа коллекции, ещё некоторые другие параметры, т.е. чтобы мой конструктор
выглядел вот так:
public MyCollectionEditor (Type collection_type, SomeType additional_data)
Так вот, возможно ли как-то прикрутить мой MyCollectionEditor к редактированию коллекции
в 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, то все работало, но я не мог тогда использовать свою модальную форму для выбора единицы измерения.
Люди добрые помогите, или подскажите, что читать. У меня уже истерика начинается.
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;
}
Далее при реализации выбора сущности из БД делаем чего-то такое:
А пол, которое редактируем (скажем какое-то подразделение)
отображаем так:
[Browsable(true)]
[DisplayNameLocalized(typeof (YearRequestByMonthRptConfigResources), "Department")]
[Editor(typeof (DepartmentSelectEditor), typeof (UITypeEditor))]
public EntityHolder Department
{
get { return department; }
set { department = value; }
}
Приветствую.
Есть непонятка с локализацией. Т.е., например, задан [DisplayName("Адрес сервера")], а надо что бы текст, отображаемый в PropertyGrid, был в соответствии с текущей локалью без внесений изменений в код. Решение нашёл в следующей статье — http://rsdn.ru/article/dotnet/dnetappcfg.xml
— т.е. в атрибуте DisplayName задаю имя строки в ресурсном файле, а во врапере для неё получаю значение из файлов ресурсов требуемой локали. Только при этом, пока не разобрался почему, не работает приведённый в данной статье метод сортировки при помощи атрибута PropertyOrder . Подозреваю, вернее даже почти уверен, что у меня во врапере какая-то недоработка, которую в ближайшее время найду, но если у автора статьи (или может кто ещё решал этот вопрос) есть варианты решения проблемы локализации, то было бы интересно ознакомится.
Здравствуйте, weakfish, Вы писали:
W>(или может кто ещё решал этот вопрос) есть варианты решения проблемы локализации, то было бы интересно ознакомится.
Здравствуйте, Odi$$ey, Вы писали:
OE>Здравствуйте, weakfish, Вы писали:
W>>(или может кто ещё решал этот вопрос) есть варианты решения проблемы локализации, то было бы интересно ознакомится.
OE>Re[2]: PropertyGrid FAQ
Для локализации свойств (DisplayNameAttribute) и описаний (DescriptionAttribute) этот вариант подходит, а с CategoryAttribute не получается, потому как у него нет свойства CategoryValue, а строка Category доступна только на чтение .
Здравствуйте, weakfish, Вы писали:
W>Здравствуйте, Odi$$ey, Вы писали:
OE>>Здравствуйте, weakfish, Вы писали:
W>>>(или может кто ещё решал этот вопрос) есть варианты решения проблемы локализации, то было бы интересно ознакомится.
OE>>Re[2]: PropertyGrid FAQ
W>Для локализации свойств (DisplayNameAttribute) и описаний (DescriptionAttribute) этот вариант подходит, а с CategoryAttribute не получается, потому как у него нет свойства CategoryValue, а строка Category доступна только на чтение .
А, точно, не подумал, что можно через базовый конструктор, сделал через — public CategoryLocAttribute(string resId) : base(rm.GetString(resId)) — работает.
Попытка использовать 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 с сообщением:
"Для данного объекта не определено беспараметрических конструкторов."
Но есть один вопрос:
Делаю всплывающий список, в котором выбираю строковые значения для свойства (через TypeConverter). Значения беру из базы. Но со строками работать не очень хорошо в моем случае. Хочется, чтобы пользователь выбирал строковые значения, но свойству присваивался соотетствующий ID строки. То есть подгружать из базы пары ID + Text. А при выборе свойству присваивать ID.
Здравствуйте, <Аноним>, Вы писали:
А>Мне же нужно, чтобы конструктор моего класса MyCollectionEditor, принимал А>помимо типа коллекции, ещё некоторые другие параметры…
Фак суперский вот только возник маленький вопросик. Как сделать так чтобы выпадающий список закрывался не только по нажатию интера но и при клике мышью.
Мне понадобилось воткнуть listbox теперь думаю как его красиво закрыть после выбора, а в факе нет исходника класса ForeignLangsControl что бы посмотреть что там делается по нажатию кнопочки.
Здравствуйте, 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
АК>Авторы: АК> Алексей Кирюшкин
АК>Аннотация: АК>Как заменить имя переменной в левой колонке “человеческим” именем свойства? АК>Как отобразить расширенную подсказку по свойству в нижнем окне? АК>Как сгруппировать свойства по категориям? АК>Как отобразить свойство, недоступное для редактирования? АК>Как заменить стандартные True/False в отображении свойств типа bool? АК>Как заменить стандартное отображение имен членов перечисления? АК>Как показать свою картинку для каждого значения из перечисления? АК>Как организовать выбор значения из выпадающего списка, формируемого программно? АК>Как реализовать отображение составного свойства? АК>Как организовать выбор файла с заданным расширением? АК>Как организовать редактирование свойства в собственной форме? АК>Как организовать редактирование свойства в выпадающем списке? АК>Как управлять видимостью свойства в зависимости от значения другого свойства? АК>Как избавиться от стандартного “(Collection)” в правой колонке для свойств-коллекций? АК>Как заменить стандартные подписи (Members, properties) в окне Collection Editor? АК>Как добавить в Collection Editor окно с расширенной подсказкой по редактируемым свойствам? АК>Как задать отличный от алфавитного порядок следования свойств внутри категории? АК>Как запомнить и восстановить положение разделителя колонок в PropertyGrid?
а есть ли где нибудь вариант того как сделать это в managed c++ ???
пытался сам переделать, но все равно осталась куча ошибок, к которым без понятия с какого боку подходить. Может кто тоже уже пытался это сделать?
Re[2]: PropertyGrid FAQ
От:
Аноним
Дата:
16.10.07 08:18
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Алексей Кирюшкин, Вы писали:
АК>>Статья: АК>>PropertyGrid FAQ
АК>>Авторы: АК>> Алексей Кирюшкин
АК>>Аннотация: АК>>Как заменить имя переменной в левой колонке “человеческим” именем свойства? АК>>Как отобразить расширенную подсказку по свойству в нижнем окне? АК>>Как сгруппировать свойства по категориям? АК>>Как отобразить свойство, недоступное для редактирования? АК>>Как заменить стандартные True/False в отображении свойств типа bool? АК>>Как заменить стандартное отображение имен членов перечисления? АК>>Как показать свою картинку для каждого значения из перечисления? АК>>Как организовать выбор значения из выпадающего списка, формируемого программно? АК>>Как реализовать отображение составного свойства? АК>>Как организовать выбор файла с заданным расширением? АК>>Как организовать редактирование свойства в собственной форме? АК>>Как организовать редактирование свойства в выпадающем списке? АК>>Как управлять видимостью свойства в зависимости от значения другого свойства? АК>>Как избавиться от стандартного “(Collection)” в правой колонке для свойств-коллекций? АК>>Как заменить стандартные подписи (Members, properties) в окне Collection Editor? АК>>Как добавить в Collection Editor окно с расширенной подсказкой по редактируемым свойствам? АК>>Как задать отличный от алфавитного порядок следования свойств внутри категории? АК>>Как запомнить и восстановить положение разделителя колонок в PropertyGrid?
А>а есть ли где нибудь вариант того как сделать это в managed c++ ??? А>пытался сам переделать, но все равно осталась куча ошибок, к которым без понятия с какого боку подходить. Может кто тоже уже пытался это сделать?
конкретно интересует вопрос "Как управлять видимостью свойства в зависимости от значения другого свойства?"
У меня вопрос, который уже задавался в этом и других форумах, но ответа я нигде не видел.
Есть ли фозможность менять цвет, фонт у отдельных строк PropertyGrid?
Например, некоторые свойства пользователь должен поменять, они пусть будут синие.
Некоторые — трогать нежелательно (но можно), пусть будут серыми и т.п.
спасибо огромное за статью!
но, у меня возник, надеюсь интересный, вопрос.
мне нужно показывать и менять значения даты и времени в PropertyGrid. к обработке даты претензий не имею — автоматически вызывается DateTimeEditor. а вот как мне заставить этот эдитор показывать и редактировать время?
я это вижу примерно так: где-то нужно задать CustomFormat для отображения времени, убрать стандартный редактор даты + повесить кнопочки up/down, но я незнаю где и как это все задается.
заранее спасибо.
Здравствуйте, vehfl, Вы писали:
ZM>>В данной статье освещается вопрос — Как управлять видимостью свойства в зависимости от значения другого свойства? ZM>>Каким образом можно реализовать, чтобы видимость одного свойства зависела от значения ДРУГИХ СВОЙСТВ(не одного, а нескольких). V>Актуальный и для меня вопрос. V>Никто его не может подсказать?
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, vehfl, Вы писали:
ZM>>>В данной статье освещается вопрос — Как управлять видимостью свойства в зависимости от значения другого свойства? ZM>>>Каким образом можно реализовать, чтобы видимость одного свойства зависела от значения ДРУГИХ СВОЙСТВ(не одного, а нескольких). V>>Актуальный и для меня вопрос. V>>Никто его не может подсказать?
_FR>[C# 2.0] Динамическое управление набором свойств
V>>а не могли бы Вы выслать исходные коды на [chandif собака gmail точка com]
_FR>Всё необходимое в посте есть В чём сложности?
лень, было соображалку включать, но спасибо разобрался)))...
такой вопрос, а как можно для своего класса два различных TypeConvertera ?
те я хочу получить что то типа
[TypeConverter(typeof(PropertySorter))] -- для управления сортировкой
[TypeConverter(typeof(ComponentTypeConverter))] -- для управления видимостью и редактированием
public class MyClass : Component
{
...
}
public class ComponentTypeConverter : CustomPropertiesTypeConverter<MyClass>
{
...
}
class PropertySorter : ExpandableObjectConverter
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, vehfl, Вы писали:
V>>такой вопрос, а как можно для своего класса два различных TypeConvertera ?
_FR>И какой из двух должен будет быть создан при таком вот вызове: _FR>
что то я не совсем понял((...
подозреваю что какой вопрос такой и ответ
пояснения чего я хочу получить в итоге:
если коротко хочется чтобы мой класс обладал возможностью указания сортировки полей посредством задания атрибута TypeConverter с параметром PropertySorter, а также возможностью регулировки видимости и возможностью редактирования полей согласно описанному вами примеру
в данный момент я не совсем понимаю как это я могу сделать((
так как, когда пишу
[TypeConverter(typeof(ComponentTypeConverter))]
[TypeConverter(typeof(PropertySorter))]
public class MyClass
или
[TypeConverter(typeof(ComponentTypeConverter), (typeof(PropertySorter))]
public class MyClass
Здравствуйте, 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.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, vehfl, Вы писали:
V>>пояснения чего я хочу получить в итоге:
_FR>Это понятно. Я пытался показать, почему подобное невозможно. У типа может быть только один конвертер (в данный момент времени), поэтому надо либо в одном конверторе реализовать всю необходимую функциональность, либо поиграть с ICustomTypeDescriptor-ом, что бы в зависимости от ситуации он возвращал тот или иной конвертер.
понятно...
но это какое то странное ограничение... либо реализовано как то не так )
потому что я реализовал то, что мне нужно следующим образом:
[TypeConverter(typeof(PropertySorter))]
public class MyClass
...
[TypeConverter(typeof(ComponentTypeConverter))]
public class MyClassChild : MyClass
в итоге атрибуты в MyClassChild сортируются согласно PropertySorter, и я могу регулировать видимость и редактируемость атрибутов посредством ComponentTypeConverter
Здравствуйте, vehfl, Вы писали:
V>в итоге атрибуты в MyClassChild сортируются согласно PropertySorter, и я могу регулировать видимость и редактируемость атрибутов посредством ComponentTypeConverter
Здравствуйте, Владимир Л., Вы писали:
ВЛ>Есть ли фозможность менять цвет, фонт у отдельных строк PropertyGrid? ВЛ>Например, некоторые свойства пользователь должен поменять, они пусть будут синие. ВЛ>Некоторые — трогать нежелательно (но можно), пусть будут серыми и т.п.
Спасибо за статью. А никто не подскажет, можно ли перехватить управление в момент, когда PropertyGrid только собирается вызвать SetValue у соответствующего дескриптора? Есть событие PropertyValueChanged, но, к сожалению, PropertyValueChanging отсутствует Покопался Рефлектором в кишках, ничего интересного не нашел
Есть ли решение для форматирования отображаемых в гриде строк?
например, требуется отобразить значение типа double, с применением строки форматирования "F2"...
АК>Аннотация: АК>Как управлять видимостью свойства в зависимости от значения другого свойства?
Пытался прикрутить к кастомному 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
Проблема в выделенной строке. До присваивания 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;
}