|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Как прикрутить в WinForms приложении INotifyPropertyChanged и реакцию на OnPropertyChanged? Вот МС пример: https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-property-change-notification Код: 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.
Этот пример понятен, но здесь обработчик события в том же классе, а мне надо, чтобы при изменении значения переменной в одном объекте реагировали объекты другого класса. Как такое прикрутить? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 14:38 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Объект который зависит от Person подпишется на его событие и когда событие будет возбуждено выполнится тот метод, который вы добавили к делегату события. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 14:40 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Roman MejtesОбъект который зависит от Person подпишется на его событие и когда событие будет возбуждено выполнится тот метод, который вы добавили к делегату события. ок, это как реализовать: "Объект который зависит от Person подпишется на его событие" ? (в уже существующем приложении) Есть объект другого класса, как сделать его зависимым от Person? Реально у меня в приложении есть класс апп сеттингов, и когда юзер менятем значение какой-то настройки надо чтобы код в другом объекте понимал, что есть изменения и свежее значение перечитывалось ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 15:04 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Код: c# 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 15:14 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
События C# по-человечески: https://habr.com/ru/post/213809/ ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 15:17 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kнадо чтобы код в другом объекте понималНу так этот другой объект и должен подписываться на события в классе аппсеттингов ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 15:21 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Shocker.ProНу так этот другой объект и должен подписываться на события в классе аппсеттинговТолько надо не забывать отписываться при уничтожении этого "другого объекта", иначе будет утечка памяти. Ну или использовать подходы WeakEvents ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 15:24 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Shocker.Pro256kнадо чтобы код в другом объекте понималНу так этот другой объект и должен подписываться на события в классе аппсеттингов Не совсем понятно зачем в примере выше нужно выводиться из INotifyPropertyChanged, можно и без него создать событие и подписаться на него извне. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 16:24 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
главное помнить один момент когда объект с коротким сроком жизни (объекта А) подписывается на объект срок жизни которого длительный (объект B) К примеру, ваш конфиг, скорее всего статический, по этому все порожденные экземпляры объектов связанные с конфигурацией будут иметь срок жизни, пока ваш процесс выполняется. Подписавшись на событие объекта (B) из объекта (А) в экземпляр делегата объекта (B), сохранится указатель на объект (A). Следовательно, если ваша ссылка на объект (А) будет удалена (вами), она всё еще будет в экземпляре делегата класса (B) и GC не удалит этот объект (A) из памяти. Если таких объектов будет 100500 и они будут то загружаться, то "удаляться", то количество этих объектов будет увеличиваться, а скорость обратного вызова через делегат деградировать. Возникнет "утечка" памяти, так как объект вам уже не нужен, но ссылка на него всё еще существует. Более того вызов события будет приводить к выполнению этого события в класс (А). То есть когда мы из объекта (А) подписываемся на событие объекта (B), мы просто сохраняем в поле типа делегат объекта (B) ссылку на метод который необходимо запустить и ссылку на сам этот объект (чтоб можно было передать аргумент this). ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 16:58 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Roman Mejtesглавное помнить один момент когда объект с коротким сроком жизни (объекта А) подписывается на объект срок жизни которого длительный (объект B) К примеру, ваш конфиг, скорее всего статический, по этому все порожденные экземпляры объектов связанные с конфигурацией будут иметь срок жизни, пока ваш процесс выполняется. Подписавшись на событие объекта (B) из объекта (А) в экземпляр делегата объекта (B), сохранится указатель на объект (A). Следовательно, если ваша ссылка на объект (А) будет удалена (вами), она всё еще будет в экземпляре делегата класса (B) и GC не удалит этот объект (A) из памяти. Если таких объектов будет 100500 и они будут то загружаться, то "удаляться", то количество этих объектов будет увеличиваться, а скорость обратного вызова через делегат деградировать. Возникнет "утечка" памяти, так как объект вам уже не нужен, но ссылка на него всё еще существует. Более того вызов события будет приводить к выполнению этого события в класс (А). То есть когда мы из объекта (А) подписываемся на событие объекта (B), мы просто сохраняем в поле типа делегат объекта (B) ссылку на метод который необходимо запустить и ссылку на сам этот объект (чтоб можно было передать аргумент this). Лайкнул, спасибо ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:07 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kНе совсем понятно зачем в примере выше нужно выводиться из INotifyPropertyChanged, можно и без него создать событие и подписаться на него извне.Хм. Перепроверил автора топика - так это ж ты и предложил INotifyPropertyChanged. Просто INotifyPropertyChanged - это паттерн. Если он тебе не нужен - ну значит не нужен. Смысл есть, когда один обработчик обрабатывает много разных событий многих разнотипных объектов. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:13 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kINotifyPropertyChangedэто событие для биндинга обычно. А для своих дел можно использовать хоть MyEvent. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:16 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Roman Mejtes, Если коротко, то нужно отписываться, т.к.сборщик мусора это не умеет. Что отписываться выше говорилось. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:18 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Лично я сделал себе централизованный уведомитель для подобных целей, уведомления уровня приложения. Уведомитель-синглтон принимает от желающих подписки на определенные события, другие желающие могут их возбуждать. Соответственно, реализовано через слабосвязанные события, так что отписка не требуется ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:35 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Shocker.ProУведомитель-синглтона если в главной форме? И достать всегда можно. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:37 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Petro123а если в главной форме? И достать всегда можно.да без разницы ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 17:38 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Shocker.Pro256kНе совсем понятно зачем в примере выше нужно выводиться из INotifyPropertyChanged, можно и без него создать событие и подписаться на него извне.Хм. Перепроверил автора топика - так это ж ты и предложил INotifyPropertyChanged. Просто INotifyPropertyChanged - это паттерн. Если он тебе не нужен - ну значит не нужен. Смысл есть, когда один обработчик обрабатывает много разных событий многих разнотипных объектов. Да не я, это у майкрософта написано ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 18:12 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Petro123256kINotifyPropertyChangedэто событие для биндинга обычно. А для своих дел можно использовать хоть MyEvent. Спасибо, Пэдро, теперь понял ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 18:13 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kНе совсем понятно зачем в примере выше нужно выводиться из INotifyPropertyChanged, можно и без него создать событие и подписаться на него извне. 256k Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9.
Большинство стандартных контролов умеют "правильно реагировать" на соответствующее событие подвязанного источника данных (см. binding). Т.е., разработчику не нужно "вручную" разруливать событие из другого потока, выставлять свойства контрола в соответствие новому значению, отписываться от события и т.п. Типа, создал связь (binding) с источником данных - и забыл, примерно для этого. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.01.2019, 18:22 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Roman Mejtesглавное помнить один момент когда объект с коротким сроком жизни (объекта А) подписывается на объект срок жизни которого длительный (объект B) К примеру, ваш конфиг, скорее всего статический, по этому все порожденные экземпляры объектов связанные с конфигурацией будут иметь срок жизни, пока ваш процесс выполняется. Подписавшись на событие объекта (B) из объекта (А) в экземпляр делегата объекта (B), сохранится указатель на объект (A). Следовательно, если ваша ссылка на объект (А) будет удалена (вами), она всё еще будет в экземпляре делегата класса (B) и GC не удалит этот объект (A) из памяти. Если таких объектов будет 100500 и они будут то загружаться, то "удаляться", то количество этих объектов будет увеличиваться, а скорость обратного вызова через делегат деградировать. Возникнет "утечка" памяти, так как объект вам уже не нужен, но ссылка на него всё еще существует. Более того вызов события будет приводить к выполнению этого события в класс (А). То есть когда мы из объекта (А) подписываемся на событие объекта (B), мы просто сохраняем в поле типа делегат объекта (B) ссылку на метод который необходимо запустить и ссылку на сам этот объект (чтоб можно было передать аргумент this). Кстати, а как бы отписать всех обработчиков? т.е. я могу не знать кто уже подписался и сколько подписчиков, но знаю, что пора "делать ноги". ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 12:58 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256k, При закрытии приложения не надо отписывать. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 13:08 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kКстати, а как бы отписать всех обработчиков? т.е. я могу не знать кто уже подписался и сколько подписчиков, но знаю, что пора "делать ноги".Если предполагается уничтожить экземпляр класса, НА события которого кто-то подписался, то ничего страшного, он уничтожится, так как на него ссылок нет, это наоборот - он содержит ссылки на подписчиков. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 13:17 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256k, Для начала, стоит задать вопрос, что такое событие? Событие по своей сути очень похоже на Свойство класса, это надстройка над полем класса, позволяющая добавить уровень абстракции. Свойство реализуется 2 методами Get и Set над полем класса заданного типа. Событие реализуется 2 методами Add и Remove, а в качество поля используется делегат заданного типа. В обоих случая мы можем не определять реализацию методов свойства или события явно, за нас это делает компилятор. по этому будет достаточно написать: Код: c# 1.
Всё остальное за нас сделает компилятор, в результате его работы получится, нечто похожее на то, что написано ниже. Но если реализация объявлена явно, мы можем добавить свой код, к примеру, код проверки значения свойства или проверки объекта который пытается подписаться на наше событие. По факту мы можем сделать так, что подписываясь на событие, объекту будет в этом отказано и ссылка которую он передает на метод и объект не будет добавлена в делегат, или будет добавлена сразу в 2, а возможно я создам таблицу, в которой буду хранить все объекты, которые добавлены в делегате. Вариантов море. Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Поле типа делегат это объект ссылочный тип похожий на список, в нём хранятся ссылки на методы и если мы добавляем в делегат метод экземпляра объекта, ссылка на этот объект. Удалив делегат, обнулив его, мы потеряем все указатели на эти объекты и методы, а через какое то время GC грохнет этот объект и все те объекты, на которые он ссылается, так как все они больше не имеют корневого объекта Код: 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. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100.
Результат выполнения: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Всё это довольно просто и весело, когда вы работаете в 1 потоке, но когда приложение многопоточное, наступает жопа, так как добавление обработчика события операция не атомарная (мягко говоря). По этому, в тот момент, когда объект подписывается или отписывается на событие, оно может быть возбуждено. Если объект отписывается, он может быть уже не готов его обработать, но ссылка в делегате всё еще существует, такая ситуация может привести к исключению или другим неприятным последствиям. Но это тема для другой темы. если где я не прав, пусть меня поправят, я же не Троелсен :D ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 14:12 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Roman MejtesВсё это довольно просто и весело, когда вы работаете в 1 потоке, но когда приложение многопоточное, наступает жопа, так как добавление обработчика события операция не атомарная (мягко говоря). По этому, в тот момент, когда объект подписывается или отписывается на событие, оно может быть возбуждено. Если объект отписывается, он может быть уже не готов его обработать, но ссылка в делегате всё еще существует, такая ситуация может привести к исключению или другим неприятным последствиям. Но это тема для другой темы. если где я не прав, пусть меня поправят, я же не Троелсен :D Эта проблема подписчика ("он может быть уже не готов его обработать"), по-моему, надуманна (сначала отпишись, затем отключай готовность обрабатывать). А вот "возбуждение" события действительно может быть проблемным. Такая конструкция (беспроблемная) возможна лишь начиная с C#6 Код: c# 1. 2.
а вот такая конструкция очень даже проблемная (потоконезащищенная) Код: c# 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 14:58 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
LRRoman MejtesВсё это довольно просто и весело, когда вы работаете в 1 потоке, но когда приложение многопоточное, наступает жопа, так как добавление обработчика события операция не атомарная (мягко говоря). По этому, в тот момент, когда объект подписывается или отписывается на событие, оно может быть возбуждено. Если объект отписывается, он может быть уже не готов его обработать, но ссылка в делегате всё еще существует, такая ситуация может привести к исключению или другим неприятным последствиям. Но это тема для другой темы. если где я не прав, пусть меня поправят, я же не Троелсен :D Эта проблема подписчика ("он может быть уже не готов его обработать"), по-моему, надуманна (сначала отпишись, затем отключай готовность обрабатывать). Наверное, речь шла о проблеме #4 вот в этой статье https://www.codeproject.com/Articles/886223/Csharp-Multithreading-and-Events, тогда да, ее нужно решать... ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 15:13 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
LR, Ну это ж потоки. Автору не надо. Там всегда не просто. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 15:18 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Petro123LR, Ну это ж потоки. Автору не надо. Там всегда не просто. да к.е.з., может и надо ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 15:37 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
256kPetro123LR, Ну это ж потоки. Автору не надо. Там всегда не просто. да к.е.з., может и надо ... |
|||
:
Нравится:
Не нравится:
|
|||
23.01.2019, 15:50 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Shocker.ProЛично я сделал себе централизованный уведомитель для подобных целей, уведомления уровня приложения. Уведомитель-синглтон принимает от желающих подписки на определенные события, другие желающие могут их возбуждать. Соответственно, реализовано через слабосвязанные события, так что отписка не требуется Интересная идея, можно для примера подробнее? или ссылку какую? ... |
|||
:
Нравится:
Не нравится:
|
|||
29.01.2019, 13:10 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Что именно тут требует пояснения? Есть метод, который принимает от желающих делегат и некий ключ, который является как бы именем подписки, и складывает полученные делегаты в словарик под этим ключом. Есть метод, возбуждающий это событие по тому же ключу - просто достает из словарика все делегаты, соответствующие этому ключу и вызывает их по очереди. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.01.2019, 13:16 |
|
OnPropertyChanged
|
|||
---|---|---|---|
#18+
Shocker.ProЧто именно тут требует пояснения? Есть метод, который принимает от желающих делегат и некий ключ, который является как бы именем подписки, и складывает полученные делегаты в словарик под этим ключом. Есть метод, возбуждающий это событие по тому же ключу - просто достает из словарика все делегаты, соответствующие этому ключу и вызывает их по очереди. спасибо, сделал через синглетон - работает, как надо! ... |
|||
:
Нравится:
Не нравится:
|
|||
29.01.2019, 15:09 |
|
|
start [/forum/topic.php?all=1&fid=20&tid=1399097]: |
0ms |
get settings: |
8ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
55ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
59ms |
get tp. blocked users: |
1ms |
others: | 15ms |
total: | 169ms |
0 / 0 |