|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Хочу сделать такой класс-обёртку, чтобы принимал в конструкторе значение любого типа и присваивал это значение своей внутренней переменной, отвечающей за хранение значения. Естественно, это значение из обёртки должно быть удобно привязывать потом к элементам интерфейса. Что-то типа такого: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
Вообще, задача такая - есть в модели (у меня MVVM) много параметров в виде интов, даблов и даже сложных типов. У каждого из параметров есть ограниченный набор атрибутов, типа Range, Display. Хочу отображать и значение параметров, и значения их атрибутов в интерфейсе. Предлагают делать для этого конвертер и через него вытаскивать из атрибутов значения. Я попробовал - получилось. Но если приходится привязываться не только к значению атрибута, а и к тому, есть ли это значение или нет (т. е. привязка к типу bool), да плюс типов значений параметров много (инты, даблы, дисималы и прочие) то приходится на каждый возвращаемый тип делать по своему конвертеру. А кроме того, способ, которым можно вытащить с помощью конвертера значения из атрибутов, слишком многословен в XAML-разметке, т. к. информацию о типе модели, имени свойства модели, типе атрибута и имени свойства атрибута приходится передавать именно там. Так вот, решил спросить, правильный ли у меня подход для этой типичной задачи - что для подобных вещей делается обёртка в модели представления, в которую вытаскиваются все данные из модели, и потом уже эта обёртка привязывается к интерфейсу. Или сделать через конвертеры в XAML, которые будут вытаскивать данные из модели сами, но с кучей удочняющего синтаксиса. В первом случае я логику по вытаскиванию метаданных из атрибутов переношу из конвертеров в класс-обёртку. Ну и как вообще это делается у вас? ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 10:54 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Если нельзя для любого типа, то хотя бы две обёртки - одну для хранения значений и метаданных типов значений, а другую - для ссылочных типов. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 10:54 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Естественно, что если в обёртку вытаскивать все данные из атрибутов, то к полю _value добавятся ещё поля типа _valueName, _valueDescription, _maxValue, _minValue и т. д. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 11:00 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
авторесть ли это значение или нет (т. е. привязка к типу bool), да плюс типов значений параметров много (инты, даблы, дисималы и прочие) то приходится на каждый возвращаемый тип делать по своему конвертеру. Для подобных целей есть универсальный Nullable<T>, у которого есть свойство HasValue ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 11:18 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
SeVaавторесть ли это значение или нет (т. е. привязка к типу bool), да плюс типов значений параметров много (инты, даблы, дисималы и прочие) то приходится на каждый возвращаемый тип делать по своему конвертеру. Для подобных целей есть универсальный Nullable<T>, у которого есть свойство HasValue Да, но как быть со значениями атрибутов? Их через конвертеры показывать или через обёртку? Если через конвертер, то в случае, когда надо просто показать название параметра, замл будет выглядеть так: (здесь MetadataParameters - тип, в котором хранятся значения, нужные для доставания значения конкретного свойства конкретного атрибута; объект этого типа используется как параметр конвертера; конвертер достаёт нужное значение из атрибута модели) Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
Не правда ли, слишком многословно? Для отображения четырёх значений атрибутов для всего лишь одного параметра потребуется более одного экрана разметки. А кроме того, представление зачем-то получает сведения о составе модели, что противоречит принципам MVVM. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 11:34 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Нет, Nullable<T> не походит, т. к. тип данных я узнаю только во время выполнения программы. Можно использовать тип dynamic, как я понимаю... Но меня всё равно интересует общепринятый подход к проблеме, что я изложил. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 13:22 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
user7320Нет, Nullable<T> не походит, т. к. тип данных я узнаю только во время выполнения программы. Можно использовать тип dynamic, как я понимаю... Но меня всё равно интересует общепринятый подход к проблеме, что я изложил. Он не подходит только тем кому нравится писать конвертеры для каждого типа. ЗЫ А кому и для чего нужны подобные мультики <Binding.ConverterParameter> <Converters:MetadataParameters ModelType="{x:Type SettingsModels:Common}" ModelProperty="ExceedThreshold" AttributeType="{x:Type Attributes:NameDescriptionAttribute}" AttributeProperty="Name" /> </Binding.ConverterParameter> вместо того, чтобы просто указать номальный binding? В чем тут профит? Все эти игры с метаописанием кроме геморроя и лишних телодвижений ничего не дадут. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 13:41 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Если без метаописания, то как в модели сохранить данные о названии поля (нужно показывать локализованное в ГУИ), его описание (аналогично), его значение (используется в расчётах), пределы, в которых можно задавать это поле, и ещё возможно другие? Если просто к дабловому значению поля дописать ещё кучку полей, типа: double myValue; string myValueName; string myValueDescription; double myValueMax; double myValueMin; то я просто захламлю класс, в котором итак этих полей под 20 штук, кучей мусора. Будет 100 вместо 20. Это первое. А если я хочу также добавить описания и имена и для ссылочных типов, а не только для типов значений? Т. е. есть класс настроек - у него 20 настроек-полей. Я хочу описания и прочее не только для отдельных настроек, но и для самого слова "настройки" (т. е. для объекта класса настроек). Потому как могут быть "настройки такого-то режима расчёта", "настройки другого режима расчёта" и т. д. Вообще, задача распространённая: обычные группированные настройки с подсказками для каждой группы и каждоу отдельной настройки. Я хотел узнать, как эту задачу обычно решают? Что, каждый свой велосипед мастерит? Вот мне подсказали, что свойства свойств - это метаданные свойств. По моим описаниям как раз выходит, что надо использовать метаданные. Если бы их надо было забайндить сразу в представление, то ещё полбеды. А их надо забайндить из модели в представление через модель представления (MVVM). Потому как эта же модель - с настройками и логикой расчёта - может у нас быть использована не только для WPF-приложений, а, например, для связки веб-служба и веб-интерфейс, или веб-служба и Сильверлайт-ГУИ на телефоне. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 18:49 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Есть ещё вариант описанной мной обёртки, но сразу для модели. Но тогда многословность возникает при расчёте, когда данные из модели выбираешь для расчёта. Ещё был вариант, сделать сложную модель с обёртками - для работы с моделью представления, и простой вариант безо всяких описаний - для расчётов. Но это, по-моему, пложение сущностей без причины. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 18:51 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Ну а так я с вами согласен, что в WPF и XAML нет удобного способа для доступа к метаданным и их байндинга. Приходится свои многоэтажные костыли громоздить. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 18:52 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Мне ещё не нравится, что я в конвертере не использую значение, получаемое из байндинга - все необходимые для конвертера данные берутся из параметра, а байндинг используется только для того, чтобы вернуть из конвертера значение в соответствующий контрол. По идее, конвертер тут лишний. Поэтому я и хочу обернуть модель в обёртку в модели представления и на этапе инициализации обёртки выполнить всю логику конвертера. А далее уже байндить обёртку к контролам с уже полученными значениями - т. е. обойтись без конвертеров. Вот только с универсальностью обёртки, подходящей подо все типы, у меня и возникли проблемы. А подход, я думаю, у меня правильный. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.02.2013, 22:22 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
user7320Я хотел узнать, как эту задачу обычно решают? Что, каждый свой велосипед мастерит? если я правильно понял тему, то наверное, да)) пример "велосипеда" можно посмотреть у самих же мокрософтов - например, System.ComponentModel.DataAnnotations, в SL DataForm, см. Source code.zip\Controls.Data.DataForm.Toolkit\DataForm (исходники доступны для свободного скачивания) ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2013, 00:54 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
LRuser7320Я хотел узнать, как эту задачу обычно решают? Что, каждый свой велосипед мастерит? если я правильно понял тему, то наверное, да)) пример "велосипеда" можно посмотреть у самих же мокрософтов - например, System.ComponentModel.DataAnnotations, в SL DataForm, см. Source code.zip\Controls.Data.DataForm.Toolkit\DataForm (исходники доступны для свободного скачивания) Я ему об этом уже говорил. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2013, 08:26 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Ну, раз каждый свой велосипед, а мои предложения по обёртке выглядят логичными (ведь логичными?), то я спокоен - я делаю правильно, с учётом косяков и вынужденных костылей текущих инструментов. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2013, 10:55 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
user7320, велосипед каждый изобретает под себя, я бы вместо конвертеров использовал индексированные свойства, да и вместо обёртки снес бы всю эту кухню в базовый класс... Навскидку, весьма упрощенно: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44.
... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2013, 13:11 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
LR, Спасибо, подход интересный. Наверное, я и буду его использовать. Мне только не нравится, что в привязках в представлении всё равно раскрываю структуру модели, и что изобретается своя нотация при привязке для выбора нужных атрибутов нужных свойств. Если у атрибута не одно свойство, а кучка, то нужно ещё третье слово через подчёркивание вводить - имя свойства уже атрибута. Т. е. по сути та же штука, что и у меня с конвертерами, только менее многословная. Однако, как я понял, у вас это всё в модели представления. А у меня атрибуты - в модели. Нужен ещё шаг по копирования атрибутов из модели в модель представления. Ну, или завести в модель представления поле с объектом модели (это и так делается по шаблону MVVM), и надёргать значения атрибутов в словарь уже из него. А зачем у вас статический словарь _propattrs? Его же сборщик мусора очень долго убирать не будет. Не лучше ли сделать его публичным полем конкретного экземпляра и хранить там только значения атрибутов конкретного экземпляра? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2013, 15:43 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
user7320что изобретается своя нотация при привязке для выбора нужных атрибутов нужных свойств.изобретателю велосипеда приходится что-то изобретать))) user7320А зачем у вас статический словарь _propattrs? Его же сборщик мусора очень долго убирать не будет. Не лучше ли сделать его публичным полем конкретного экземпляра и хранить там только значения атрибутов конкретного экземпляра?у Вас бывает что значения атрибутов в разных экземплярах разнятся??? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2013, 16:19 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
автору Вас бывает что значения атрибутов в разных экземплярах разнятся??? Ой, нет, я тогда попутал! У меня вопрос возник. Если я реализую интерфейс, например, IDataErrorInfo в своём классе, в котором уже есть индексируемые свойства, как они не попутаются с индексируемыми свойствами от интерфейса IDataErrorInfo, когда я захочу привязку делать? Ведь обращение к индексируемому свойству во время привязки будет одинаковым в любом случае (Binding ["Blah-blah"])? IDataErrorInfo просто для примера привёл - может быть любой другой интерфейс, требующий реализации индексируемых свойств. Или я чего-то недопонимаю и это два разных набора индексируемых свойства и к ним в привязке по-разному надо обращаться? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2013, 18:48 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
user7320, у изобретателя (велосипеда) всегда возникает много подобных вопросов))) ответ один - продолжать изобретать! как вариант Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80.
... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2013, 19:52 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
поправочка, вместо public object this[string prop_attr_name] { get { return _propattrs[prop_attr_name]; } } конечно public object this[string prop_attr_name] { get { return _propattrs.ContainsKey(prop_attr_name) ? _propattrs[prop_attr_name] : null; } } ... |
|||
:
Нравится:
Не нравится:
|
|||
08.02.2013, 20:05 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
LR, Спасибо за способ ещё раз. Я улучшил ваш вариант и сделал так: Класс MyMetaInfo теперь AttributesData и он считывает значения всех свойств всех атрибутов, без разбора. Немного перебираю по объёму данных, зато код короче и лаконичнее, и без жётско закодированных значений в виде строк: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41.
Базовый класс содержит в конструкторе параметр типа Type, поэтому теперь вместо this.GetType() я везде в этом классе использую этот тип. Ну, а тип в конструктор базового класса передаёт конструктор модели представления, который берёт этот тип из модели (модель представления содержит в себе объект модели). В разметке же всё выглядит так (вместо Meta у меня Attributes): Код: xml 1. 2. 3.
Проверил - работает всё, да ещё с локалями. Пока буду использовать это. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.02.2013, 21:56 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Потом посмотрю, стоит ли фильтровать собираемые свойства атрибутов, или оставить все подряд. С собираемыми избирательно пришлось бы делать проверки на тип атрибута и выбирать конкретные свойства по хардкодед именам... Уж лучше пожертвовать немного памяти и собирать все свойства, тем более - я там посмотрел - их не много. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.02.2013, 21:58 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
Вопрос к большому любителю атрибутов. Чем это Код: c# 1. 2. 3.
лучше привязки к простому ресурсному справочнику с уже готовой поддержкой локализации? Ты изгаляешься на ровном месте с практальными методами ... |
|||
:
Нравится:
Не нравится:
|
|||
10.02.2013, 22:19 |
|
Как сделать универсальную обёртку для любого типа?
|
|||
---|---|---|---|
#18+
SeVaВопрос к большому любителю атрибутов. Чем это Код: c# 1. 2. 3.
лучше привязки к простому ресурсному справочнику с уже готовой поддержкой локализации? Ты изгаляешься на ровном месте с практальными методами Ресурсный справочник у меня в модели и есть - там всякие строковые ресурсы с поддержкой локализации. Атрибуты у меня тоже с поддержкой локализации, и их строковые значения берутся как раз из этих ресурсов. Всё выглядит примерно так: модель: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9.
модель представления: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38.
Класс AttributesData вы уже видели. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.02.2013, 05:38 |
|
|
start [/forum/topic.php?fid=21&msg=38142565&tid=1441498]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
66ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
53ms |
get tp. blocked users: |
1ms |
others: | 14ms |
total: | 178ms |
0 / 0 |