Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> PropertyGrid, Или как изменять атрибуты 
:(
    Опции темы
Plamenk
Дата 25.10.2004, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 258
Регистрация: 18.2.2003

Репутация: 1
Всего: 3



Всем Привет!

Для изменения свойств объекта (во время работы программы) использую PropertyGrid. Всё бы хорошо, но мне понадобилось прятать во время выполнения программы некоторое свойств скажем XXX, когда другое свойство, предположим, YYY равно 0.

Решить эту проблему можно двумя способами:

1. В рантайме изменить атрибут (помоему, [browsable]) свойства XXX на false. Но как я не бился не нашел способа изменять атрибуты.

2. Скрывать (или хотябы затемнять) свойство XXX средствами PropertyGrid. В данном направлении мне тоже не удалось ничего сделать.

Если у кого-нибудь есть какие-нибудь идеи, пожалуйста поделитесь.

Заранее всем СПАСИБО!!!
PM MAIL   Вверх
stab
Дата 26.10.2004, 12:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



Можно получить список атрибутов через Reflection, но это ни чего не дает, т.к., судя по всему, возвращается десериализованная копия атрибутов, естественно обратно их сеарилизовать в сборку не получится. Таким образом, каждый кто обращается к атрибутам свойства, класса, т.д. получает их в неизменном виде. Создание собственного атрибута с возможность изменения параметров во время выполнения ни к чему не приведет. Пример, который доказывает это:

Код

public class MyBrowsableAttribute: Attribute
{
public MyBrowsableAttribute(bool browseable)
{
 _browseable = browseable;
}

private bool _browseable;

public bool Browseable
{
 get
 {
  return _browseable;
 }
 set
 {
  _browseable = value;
 }
}
}

public class MyClass
{
private int _intProp = 0;

[MyBrowsable(false)]
public int IntProp
{
 get
 {
  return _intProp;
 }
 set
 {
  _intProp = value;
 }
}
}

...

Type type = typeof(MyClass);
PropertyInfo propInfo = type.GetProperty("IntProp");
object[] attrs = propInfo.GetCustomAttributes(typeof(MyBrowsableAttribute), true);
MyBrowsableAttribute attr = (MyBrowsableAttribute) attrs[0];
attr.Browseable = true;

type = typeof(MyClass);
propInfo = type.GetProperty("IntProp");
attrs = propInfo.GetCustomAttributes(typeof(MyBrowsableAttribute), true);
attr = (MyBrowsableAttribute) attrs[0];
if (attr.Browseable) Text = "Ohh, it's changed!";


К сожалению сообщения "Ohh, it's changed!" мы не увидим :)

НО! Можно задать набор значений атрибутов для PropertyGrid по которым она будет отсеивать свойства:

Код

public class MyBrowsableAttribute: Attribute
{
public MyBrowsableAttribute(bool browseable)
{
 _browseable = browseable;
}

private bool _browseable;

public bool Browseable
{
 get
 {
  return _browseable;
 }
}
}

public class MyClass
{
private int _intProp = 0;

[MyBrowsable(false)]
public int IntProp
{
 get
 {
  return _intProp;
 }
 set
 {
  _intProp = value;
 }
}
}

...

private MyClass MyInstance = new MyClass();

private void Form1_Load(object sender, System.EventArgs e)
{
propertyGrid1.SelectedObject = MyInstance;
}

private void button2_Click(object sender, System.EventArgs e)
{
propertyGrid1.BrowsableAttributes = new AttributeCollection(new Attribute[] {new MyBrowsableAttribute(true)});  
}


После нажатия на button2 IntProp больше не будет отображаться в PropertyGrid. Думаю направление движения понятно ;)
Кстати, теоритически надо перекрывать Equals и GetHashCode для нашего атрибута, но как это ни странно и без этого все работает. На всякий случай, вот код:

Код

public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj == this) return true;

MyBrowsableAttribute attr = (MyBrowsableAttribute) obj;
return attr.Browseable == Browseable;
}

public override int GetHashCode()
{
return Browseable.GetHashCode();
}

Добавлено @ 12:23
з.ы. using System.Reflection; пригодится...


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
Plamenk
Дата 26.10.2004, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 258
Регистрация: 18.2.2003

Репутация: 1
Всего: 3



2 cully:

Спасибо за ответ, сегодня вечером попробую твой метод.
PM MAIL   Вверх
Plamenk
Дата 1.11.2004, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 258
Регистрация: 18.2.2003

Репутация: 1
Всего: 3



2 cully: Спасибо за идею, наверное без твоего совета ничего и не сделал! А так разобрался.

Действительно, при решении этой задачи основным свойством оказалось propertyGrid1.BrowsableAttributes. Единственное что, не првильно в методе cully это реализация класса наследника от Attribute. Но об этом чуть позже.

Сначала необходимо понять, что такое своиство propertyGrid1.BrowsableAttributes. Это свойство представлет собой коллекцию аттрибутов, а точнее коллекцию одного атрибута -"эквивалента". Т.е. в этом свойстве находиться атрибут, который propertyGrid использует для определения необходимости показа того или иного свойства объекта! Если точнее то propertyGrid ищет у свойств атриббут того же типа, что и "эквивалент" и сравнивает их. Если аттрибут свойства эквивалентен(==) атрибутту хранящимуся в BrowsableAttributes, то свойство выводиься в propertyGrid, иначе не выводится.

Это легко проверить. Если выполнить следующий код:
Код
propertyGrid1.BrowsableAttributes = new AttributeCollection(new Attribute[] {new BrowsableAttribute(false)});

После выполнения этой строчки propertyGrid1 отобразит все свойства помеченные [BrowsableAttribute(false)] и спрячет все остальные.

Таким образом, видно что propertyGrid может находиться в двух состояниях, либо показаны все свойства помеченные BrowsableAttribute(true) (по умолчанию), либо BrowsableAttribute(false). Это происходит вследствии того, что аттрибут BrowsableAttribute может быть либо false либо true. Следовательно для решения моей задачи необходимо создать свой аттрибу, который будет иметь более двух состояний. Для этого можно использовать разные методы, я же продемонстрирую метод, который использовал сам:

Код
//Код писал без VS так что могут быть синтаксические ошибки!!!!

//Создаем новый класс атрибут который будет отвечать за отображения свойств
//в propertyGrid во время выполнения
public class MyAttribute: Attribute
{

//Константы
public const uint SHOW_ALL = 0xFFFFFFFF; //Всегда выводить на экран
public const uint SHOW_NO = 0x00000000; //Никогда не выводить на экран
public const uint SHOW_1 = 0x1; //Состояние 1
public const uint SHOW_2 = 0x2; //Состояние 2
public const uint SHOW_3 = 0x4; //Состояние 3
public const uint SHOW_4 = 0x8; //Состояние 4
//... и т.д.

public MyAttribute(uint browseable)
{
Browseable = browseable;
}

public uint   Browseable;

//Перегружаем функцию сравнения она то и является главной
public override bool Equals(object obj)
{
return (((MyAttribute) obj).Browseable &  Browseable) != 0);
}

//И функцию, вообщем она не играет особой роли
public override int GetHashCode()
{
return this.GetHashCode();
}
}

//Какой-то класс, свойства которого необходимо выводить в propertyGrid
public class MyClass
{

[MyAttribute((MyAttribute.SHOW_ALL)]
public int ALL {..}

[MyAttribute((MyAttribute.SHOW_NO)]
public int NO {..}

[MyAttribute((MyAttribute.SHOW_1)]
public int P1 {..}

[MyAttribute((MyAttribute.SHOW_2)]
public int P2 {..}

[MyAttribute((MyAttribute.SHOW_3)]
public int P3 {..}

...
}

...

private MyClass MyInstance = new MyClass();

private void Form1_Load(object sender, System.EventArgs e)
{
//Отобразяться все свойства кроме помечанных SHOW_NO и, вообще, не помеченные
propertyGrid1.BrowsableAttributes = new AttributeCollection(new Attribute[] {new MyAttribute(MyAttribute.SHOW_ALL)});

propertyGrid1.SelectedObject = MyInstance;
}

//Допустим нужно спрятать P1 и P2
private void button2_Click(object sender, System.EventArgs e)
{
propertyGrid1.BrowsableAttributes = new AttributeCollection(new Attribute[] {new MyAttribute(MyAttribute.SHOW_ALL & ~MyAttribute.SHOW_1 & ~MyAttribute.SHOW_2)});
}


Ну вот собственно и Всё!
З.Ы.: Среди ограничений данного метода надо отметить, что в большинстве случаев необходим исходный код класса объекта, который нужно отображать в propertyGrid1.
PM MAIL   Вверх
stab
Дата 1.11.2004, 19:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



Мне кажется, что лучше было бы разделить кажое состоняние MyAttribute на отдельные атрибуты и потом в BrowsableAttributes заносить масив того, что надо показывать, т.е. сделать набор атрибутов, например такой: VisibleForUserAttribute, VisibleForAdminAttribute, т.д. Потом к каждому свойству прикрепить один или несколько таких атрибутов, а BrowsableAttributes динамически заносить нужный набор привилегий, например:

Код

AttributeCollection userAccess = new AttributeCollection(new Attribute[] {new VisibleForUserAttribute(true)});

AttributeCollection adminAccess = new AttributeCollection(new Attribute[] {new VisibleForUserAttribute(true), new VisibleForAdminAttribute(true)});


имхо, такая система имеет бОльшую гибкость -- не надо менять реализацию атрибутов, достаточно добавить новый и задать соответсвущий набор привелегий.


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
Plamenk
Дата 1.11.2004, 19:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 258
Регистрация: 18.2.2003

Репутация: 1
Всего: 3



2 cully:

В propertyGrid1.BrowsableAttributes должен храниться массив состоящий только из одного аттрибута. (Если я конечно правильно понял твою идею!)
PM MAIL   Вверх
stab
Дата 1.11.2004, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



Как оказалось, там можно хранить несколько атрибутов, тогда свойство будет показываться только в том случае, если удовлетворяет всем условиям. Так что, моя последняя идея не пройдет, т.к. я думал, что показывается в том случае, если удовлетворяет хотя бы одному атрибуту... хотя может быть возможна у другая декомпозиция.


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0449 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.