|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Пытаюсь освоить для себе новую тему: Attached Properties. Пытаюсь сделать списочное свойство. Реализовал так Код: 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.
Использование Код: xml 1. 2. 3. 4. 5. 6. 7. 8.
Но хотелось бы избавиться от <collections:ArrayList> Код: xml 1. 2. 3. 4. 5. 6. 7. 8.
Попробовал так, но не вышло Код: 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.
Пытался сделать по аналогии с Behaviors - тоже не вышло. Код: 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.
Код: 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.
Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
Какие есть мысли на этот счёт? ... |
|||
:
Нравится:
Не нравится:
|
|||
18.04.2020, 18:24 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
фигня какая то, если честно, они не для этого предназначены Код: c# 1.
вот тут ошибка, вы в статике объявляете экземпляр объекта List<object>, но получается, что все экземпляры объектов будут иметь общий список, ведь инстанцирование общего произошло в статике, правильно написать Null и если нужно сделать список по умолчанию инициализировать его из конструктора экземпляра, а не статического. Но упс, а как это сделать с AttachedProperty? конструктор то не доступен. По этому избавляться от ArrayList не стоит, есть еще CompositeCollection, возможно имеет смысл пользоваться ей. Для генерации элементов управления на панель используют механизм похожий на ItemsControl, в 99% этот элемент управления и его производные позволяют делать логику с большим количеством элементов, на произвольной панели, ведь представление независимо и мы можем изменить его в любое другое, вопрос полёта фантазии. Панель сама по себе содержит коллекцию объектов и можно было просто написать Код: xml 1. 2. 3. 4.
... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2020, 12:46 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Roman Mejtes фигня какая то, если честно, они не для этого предназначены Разве Interaction.Behaviors не так работает? Roman Mejtes Код: c# 1.
вот тут ошибка, вы в статике объявляете экземпляр объекта List<object>, но получается, что все экземпляры объектов будут иметь общий список, ведь инстанцирование общего произошло в статике, правильно написать Null и если нужно сделать список по умолчанию инициализировать его из конструктора экземпляра, а не статического. Да, я это знаю. И привёл примеры для показа, что таким образом XAML конструктор ошибки не выдаёт. Но как вы правили отметили, логика работы будет совсем не та что требуется. Загвоздка именно в том как инициализировать коллекцию передав ей к какому элементу она присоединена. Третий вариант сделан по подобию Interaction.Behaviors https://github.com/microsoft/XamlBehaviorsWpf/blob/master/src/Microsoft.Xaml.Behaviors/Interaction.cs Там по логике при первом обращении идёт инициализация коллекции. В Interaction.Behaviors это обращение идёт через оболочку GetBehaviors поэтому получается передать в коллекцию ссылку на родительский элемент. Я, на мой взгляд, сделал точную копию этого механизма. Но с моим кодом при исполнении XAML кода нет обращения к GetItems . XAML сразу обращается к GetValue(ItemsProperty) . По этой причине, не происходит инициализации коллекции и вылетает исключение System.Windows.Markup.XamlParseException : ""Свойство коллекции "System.Windows.Controls.StackPanel"."Items" не определено (null).": номер строки "21" и позиция в строке "18"." Roman Mejtes Для генерации элементов управления на панель используют механизм похожий на ItemsControl, в 99% этот элемент управления и его производные позволяют делать логику с большим количеством элементов, на произвольной панели, ведь представление независимо и мы можем изменить его в любое другое, вопрос полёта фантазии. Знаю и использую постоянно. В данном случае сделан простейший демо-пример, чтобы уменьшить количество деталей не относящихся к сути вопроса. Чтобы внести ясность, привожу пример сделанный по подобию Interaction.Behaviors https://github.com/microsoft/XamlBehaviorsWpf/blob/master/src/Microsoft.Xaml.Behaviors/Interaction.cs Сам пакет я не смог локально скомпилировать у себя - не хватает каких-то ссылок. Так и не разобрался откуда их взять. Реализацию у себя повторил. Здесь привожу, код только относящийся к вопросу. Коллекция для использования в свойстве. Если при инициализации передать Panel , то логика работает правильно Код: 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.
Само свойство. Если будет обращение к GetItems(Panel panel) , то всё будет работать нормально. Код: 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.
Если в XAML задать коллекцию, то окно запускается, но будет пустым. Так как коллекция "не знает" к какой панели она присоединена. Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Если панели в XAML оставить пустыми и задавать свойство в CB, то всё работает правильно. Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
Если же повторить это в XAML (так же как с Interaction.Behaviors ), то при запуске на исполнение поймаем ошибку. Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
Есть какой-то нюанс в реализации Interaction.Behaviors который я не могу уловить. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2020, 15:45 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Реализация в самом деле странная. Классы с объявленными AttachedProperty обычно ни от чего (в.т.ч. DependencyObject) не наследуют, эти классы вообще объявляют как static. Далее, пользователю желательно не давать доступа к созданию коллекции, у него должна быть возможность только объявлять элементы коллекции. В итоге получается как-то так: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
и в разметке так: Код: xml 1. 2. 3. 4. 5. 6. 7.
... |
|||
:
Нравится:
Не нравится:
|
|||
20.04.2020, 07:26 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Roman Mejtes и Сон Веры Павловны , спасибо за вниание! После ваших ответов сравнил более внимательнее свою реализацию с реализацией Behaviors. Как оказалось, в Behaviors используют нестандартную реализацию Attached Properties. У них различается названия свойств в оболочке сеттера и в регистрации свойства. Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
Подправил свою реализацию и получи то, что хотел Код: 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.
Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
То что регистрируемое имя может отличаться от имени свойства - даже в голову не приходило. Теперь заинтересовал сам механизм регистрации свойств и взаимодействи XAML с ними. Roman Mejtes и Сон Веры Павловны , если знаете, то подскажите где об этом можно глубже и подробнее прочитать. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.04.2020, 15:21 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Eld Hasp Как оказалось, в Behaviors используют нестандартную реализацию Attached Properties. У них различается названия свойств в оболочке сеттера и в регистрации свойства. Нет здесь ничего особенно нестандартного, методы GetProperty/SetProperty - это просто наименования аксессоров для доступа к DP из кода или XAML-разметки, и да, имена этих аксессоров в части указания на имя свойства могут быть любыми. Просто обычно принято, что имя свойства совпадает с именем аксессора, но если это нарушить, катастрофы не случится. Разве что от благодарных коллег можно получить по голове за такие ребуcы. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.04.2020, 17:18 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Сон Веры Павловны Нет здесь ничего особенно нестандартного, методы GetProperty/SetProperty - это просто наименования аксессоров для доступа к DP из кода или XAML-разметки, и да, имена этих аксессоров в части указания на имя свойства могут быть любыми. Просто обычно принято, что имя свойства совпадает с именем аксессора, но если это нарушить, катастрофы не случится. Разве что от благодарных коллег можно получить по голове за такие ребуcы. Я думал, для WPF - это соблюдать обязательно. Получается если есть такое зарегистрированное свойство, то код XAML обращается напрямую к нему. Если нет, то через Set/Get методы оболочки. Надо поэкспериментировать с таким необычным объявлением - как будут вести себя привязки. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.04.2020, 18:01 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
за сохранение, чтения или сброс значения свойства зависимости отвечает не свойство зависимости, а объект зависимости. А свойство зависимости является просто ключём, к этому свойству. Как сказал выше Сон Веры Павловны, это просто методы ... |
|||
:
Нравится:
Не нравится:
|
|||
20.04.2020, 23:12 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Roman Mejtes за сохранение, чтения или сброс значения свойства зависимости отвечает не свойство зависимости, а объект зависимости. А свойство зависимости является просто ключём, к этому свойству. Как сказал выше Сон Веры Павловны, это просто методы Можно сделать вывод, что при компиляции кода XAML при обращении к присоединённому свойству есть некая логика по проверке регистрации этого свойства. Если его имя зарегистрировано, то идёт обращение напрямую к Attached Propertу через obj.SetValue(...) и obj.GetValue(...) . Если не зарегистрировано, то к методам оболочки SetСвойство(obj) и GetСвойство(obj) . Для меня такая логика оказалось неожиданностью. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.04.2020, 11:32 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Eld Hasp Можно сделать вывод, что при компиляции кода XAML при обращении к присоединённому свойству есть некая логика по проверке регистрации этого свойства. Если его имя зарегистрировано, то идёт обращение напрямую к Attached Propertу через obj.SetValue(...) и obj.GetValue(...) . Если не зарегистрировано, то к методам оболочки SetСвойство(obj) и GetСвойство(obj) . Для меня такая логика оказалось неожиданностью. Опять не так. Выше подразумевалось, что для манипуляции со значениями DP объекту просто достаточно иметь само свойство, и получать/менять значения через вызовы obj.GetValue/obj.SetValue. Для внешних интерфейсов к таким вызовам делаются методы доступа, но их может и не быть (т.е. наличие методов GetProperty/SetProperty необязательно), или их имя может отличаться от имени самого свойства. А имя свойства всегда и в любом случае должно быть зарегистрировано. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.04.2020, 12:40 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Сон Веры Павловны , я за поведение XAML, если имя свойства и зарегистрированное имя различаются. В Interop от Microsoft имя свойства "Behaviors", а регистрируется "ShadowBehaviors". В своём коде, для получения такого же поведения, мне пришлось сделать так же. Получается, что XAML код по разному работает для случаев с одинаковым и разными именами свойства и регистрируемого. В случае если имена одинаковые он использует obj.Set/GetValue(СвойствоProperty,...). В случае если имена различны, я думал, что будет ошибка. А оказалось, что XAML просто переходит на использование методов оболочки Set/GetСвойство(obj,...). Вот и получается в итоге - чтобы заставить XAML работать всегда через методы оболочки, то надо ОБЯЗАТЕЛЬНО регистрировать имя отличающееся от имени свойства. Конечно, этих "танцев с бубном" можно было бы избежать, если бы был обратный вызов при инициализации свойства, по аналогии с обратным вызовом при его изменении. Но такого или нет...ну, или я не знаю о такой возможности. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.04.2020, 13:47 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Eld Hasp Вот и получается в итоге - чтобы заставить XAML работать всегда через методы оболочки, то надо ОБЯЗАТЕЛЬНО регистрировать имя отличающееся от имени свойства. А, теперь понял, о чем речь. Вот тут товарищ об этом писал: https://docs.microsoft.com/en-us/archive/blogs/johngossman/how-to-initialize-an-attached-dependencyproperty-of-type-collection The normal way to do this is to initialize the property in the CLR getter, but attached properties were skipping calling the getter. This is an optimization: the XAML parser accesses the DP directly rather than use reflection to find and call the CLR property. Well, the fix is easy: hide the DP from the XAML parser, which can be done by using a different name for the registered DP (and making it internal is a good idea), and defining the attached property by using the static getter and setter. Но здесь тоже есть один нюанс. Модифицируем мой вышеприведенный пример вот так: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
Тогда разметка должна выглядеть именно так: Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
- при парсинге пути, заданного в markup extension, всё равно работает рефлекшн, и ведется поиск указанного в пути DP, и там надо указывать именно имя DP, а не имя метода доступа - иначе будет ошибка: Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Код: plaintext 1. 2. 3. 4. 5.
... |
|||
:
Нравится:
Не нравится:
|
|||
21.04.2020, 15:24 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Сон Веры Павловны , Спасибо! Пока ясно. Теперь придумаю куда практически это можно применить. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.04.2020, 18:00 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Кстати, проверил - этот хак с разными именами самой DP и именами методов доступа/свойств в классе работает и для обычных (не attached) DP. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2020, 09:41 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
В каких практических ситуациях может пригодиться списочное атач-свойство? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.04.2020, 09:58 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
vb_sub В каких практических ситуациях может пригодиться списочное атач-свойство? Используете Interaction: Triggers и Behaviors ? Это пример списочных AP. Сейчас для своей реализации хочу сделать биндинг всплывающих RoutedCommand. Но споткнулся об область видимости привязок. Разбираюсь как это реализовано в Interaction.Behaviors ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2020, 16:36 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Сон Веры Павловны Кстати, проверил - этот хак с разными именами самой DP и именами методов доступа/свойств в классе работает и для обычных (не attached) DP. Шикарно! Это может пригодиться. Хотя у обычных DP свойств есть конструктор экземпляра в котором можно сделать инициализацию свойства экземпляра. Но как альтернативный вариант, вполне может подойти. Этот момент, для AP-свойств реализован крайне неудобно и не очевидно. MS надо было предусмотреть способ нормальной инициализации таких свойств. Но мы ей не указ... ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2020, 16:42 |
|
Освоение Attached Properties: Списочное свойство
|
|||
---|---|---|---|
#18+
Roman Mejtes , Сон Веры Павловны , "сваял" я код для практического использования такого свойства. Если будет возможность, прокомментируйте, пожпалуйста. Применил такое свойство для биндинга всплыающих RoutedComman к командам VM. Для начала создал элемент для привязки RoutedComman и команды VM. Первая часть, где объявляются два свойства соответствующего типа и создаётся экземпляр CommandBinding. К событиям CommandBinding подсоединяются защищённые методы в которых идёт обращение к полям-делегатам хранящих методы привязанной команды. Код: 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.
Вторая часть с методами обратного вызова. При изменении значений свойства RoutedComman новое значения записываются в свойство экземпляра CommandBinding.Command. При изменении значения привязанной команды VM, в делегаты записывается ссылка на методы этой команды. Код: 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.
Коллекция для RoutedCommandBinding. В конструкторе надо передать ссылку на CommandBinding. Она запоминается в свойстве только для чтения. И при изменении коллекции, вносятся соответствующие изменения в коллекцию CommandBinding Код: 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.
Само AP-свойство Код: 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.
Пример его использования Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Код: c# 1. 2. 3. 4. 5. 6. 7. 8.
Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
[youtube= ... |
|||
:
Нравится:
Не нравится:
|
|||
02.05.2020, 18:11 |
|
|
start [/forum/topic.php?fid=21&msg=39948980&tid=1440276]: |
0ms |
get settings: |
9ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
37ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
52ms |
get tp. blocked users: |
1ms |
others: | 291ms |
total: | 426ms |
0 / 0 |