|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Написал себе (и другим) шпаргалку, чтобы не забывать особенности работы с компоновкой с помощью панели. А то делаешь панели не так уж часто, и мелкие нюансы забываются. Код: 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.
Гляньте, может у кого дополнения есть, или я где-то не очень прав. В частности по поводу обрезания выходящих за границы частей (на что-то влияет ClipToBounds, на что-то нет). ЗЫ: В учебниках везде написано про измерения, что элемент возвращает желаемый размер. Но ведь это не совсем правильный термин, на мой взгляд, я употребляю слово "минимальный". Например тот же <Border /> (без настроек) затребует себе Size(0,0). ... |
|||
:
Нравится:
Не нравится:
|
|||
11.02.2019, 02:00 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Shocker.Pro, не знаю, чем вам термин желаемый размер не нравится. Так как это объект класса, с точки зрения объекта, этот как раз желаемый размер объекта, который зависит от его состояния . То есть размер который требуется элементу, для того, чтоб отобразиться в наилучшем виде (в идеале). А так шпаргалка отличная, я правда это и так всё помню ... |
|||
:
Нравится:
Не нравится:
|
|||
11.02.2019, 10:58 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Roman Mejtesне знаю, чем вам термин желаемый размер не нравится. Так как это объект класса, с точки зрения объекта, этот как раз желаемый размер объекта, который зависит от его состояния .Я трактую так: если у элемента стоит HorizontalAlignment=Stretch, то его желаемая ширина - занять всё доступное пространство. Но затребует он именно минимальное . То есть <Border BorderThickness="1" HorizontalAlignment="Stretch" /> затребует ширину в 2 дипа, даже если ему передают бесконечность в распоряжение. Roman Mejtesя правда это и так всё помню- Доктор, у меня это. Я всё забываю! - А я всё помню! Вы у меня уже были. (с) С нюансами по обрезанию пришлось поэкспериментировать. Как-то делал панель, никак не мог понять, почему элементы подрезаются, тыкал везде ClipToBounds - не помогало. То, что надо резать желаемый размер по availableSize тоже наверняка не знал, посмотрел, как штатные контролы поступают. Roman Mejtesчем вам ... |
|||
:
Нравится:
Не нравится:
|
|||
11.02.2019, 12:22 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Roman Mejtes, Подскажи, InternalChildren заведомо неизменен между MeasureOverride и ArrangeOverride? Смысл вопроса в следующем: так как зачастую основной расчет компоновки происходит уже на этапе измерения, логично было бы уже составить карту, которую просто использовать в ArrangeOverride, не обращаясь уже к коллекции InternalChildren заново. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2019, 15:07 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
И второй вопрос - нужно ли рендерить (да и измерять тоже) элементы, которые заведомо покинули область видимости при расстановке (да и при измерении)? ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2019, 15:55 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
И третий вопрос, правомерен ли комментарий: "finalSize не может быть больше availableSize"? ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2019, 22:53 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Вроде как эта тема хорошо подходит для моего вопроса. Ситуация: в листбоксе нужно отображать квадратные миниатюры неких объектов с подписью. Все квадраты должны быть одинакового размера, размер квадрата определяется длиной максимальной подписи (все подписи однострочные). Сейчас я нахожу подпись с максимальной длиной ( вот так ), и привязываю к ней ширину и высоту border'а в DataTemplate. Схематично и в упрощенном виде это выглядит так: Код: 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.
Код: xml 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.
- всё нормально и без нареканий работает, но что-то мне подсказывает, что тут правильнее было бы сделать для ListBox.ItemsPanel свою панель. Но вот как - пока не могу сообразить. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2019, 08:40 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Ну то есть ты хочешь избавится от вычисления общей ширины, которую сейчас ты вынужден вычислять вручную. Ну логично, в принципе, но в чем вопрос-то? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2019, 08:45 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Shocker.Proно в чем вопрос-то? В том, что я вообще не представляю, с какого боку тут подступиться. Допустим, я наследуюсь от WrapPanel. Что тут нужно переопределить? MeasureOverride? ArrangeOverride? Каким образом? Допустим, из InternalChildren я получу элемент с максимальной шириной - в каком из методов (и как) мне задать для всех остальных элементов аналогичную ширину и высоту? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2019, 08:58 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Нашел еще вот такое решение: Код: xml 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.
- и оно вполне работает без всяких предварительных вычислений. Теперь хотелось бы аналогичное всё-таки сделать через кастомную панель - чисто в целях самообразования, и общего развития. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2019, 09:49 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
В чем проблема то? В методе MeasureOverride вычислите все размеры для элементов панели с помощью метода child.Measure(size). Найдите максимальный размер высоты и ширины элементов. Сохраните этот размер элементов в полях панели, чтоб воспользоваться им в методе ArrangeOverride. Если в метод MeasureOverride был передан бесконечный размер, значит панель находится в прокручиваемой области. Размер будет бесконечным в том измерении, в котором разрешена прокрутка в элементе ScrollViewer. Если включена прокрутка по горизонтали, то нужно как то ограничить максимальное количество в 1 ряду, иначе все элементу будут в 1 ряд. Всё это необходимо, чтоб вычислить предполагаемый размер самой панели, которую вам нужно вернуть в конце метода. Предположим, что максимальное количество элементов в ряд 10 и панель бесконечна по вертикали и горизонтали. Тогда вы берете количество элементов делите на 10, округляете к верхней границе, получаете количество строк. Умножаете ширину элементов на 10 и высоту на количество строк, получаете размер панели. Если прокрутка только по вертикали, тогда делите ширину на полученный размер элементов, получаете количество столбцов, умножаете на ширину элементов, получаете ширину панели, вычисляете количество рядов, вычисляете высоту. Чтоб не образовывалось дыр слева, при таком раскладе, можно вычислить размер пустой области, поделить на количество столбцов и прибавить к размеру элементов. Так вы получите размер всех элементов списка. Затем в методе ArrangeOverride расположите эти элементы плиткой с вычисленным размером с помощью метода child.Arrange(rect) ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2019, 12:36 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Roman MejtesВ чем проблема то? В методе MeasureOverride вычислите все размеры для элементов панели с помощью метода child.Measure(size). Найдите максимальный размер высоты и ширины элементов. Сохраните этот размер элементов в полях панели, чтоб воспользоваться им в методе ArrangeOverride. Если в метод MeasureOverride был передан бесконечный размер, значит панель находится в прокручиваемой области. Размер будет бесконечным в том измерении, в котором разрешена прокрутка в элементе ScrollViewer. Если включена прокрутка по горизонтали, то нужно как то ограничить максимальное количество в 1 ряду, иначе все элементу будут в 1 ряд. Всё это необходимо, чтоб вычислить предполагаемый размер самой панели, которую вам нужно вернуть в конце метода. Предположим, что максимальное количество элементов в ряд 10 и панель бесконечна по вертикали и горизонтали. Тогда вы берете количество элементов делите на 10, округляете к верхней границе, получаете количество строк. Умножаете ширину элементов на 10 и высоту на количество строк, получаете размер панели. Если прокрутка только по вертикали, тогда делите ширину на полученный размер элементов, получаете количество столбцов, умножаете на ширину элементов, получаете ширину панели, вычисляете количество рядов, вычисляете высоту. Чтоб не образовывалось дыр слева, при таком раскладе, можно вычислить размер пустой области, поделить на количество столбцов и прибавить к размеру элементов. Так вы получите размер всех элементов списка. Затем в методе ArrangeOverride расположите эти элементы плиткой с вычисленным размером с помощью метода child.Arrange(rect) Ну, по сути это всё - воспроизведение логики методов MeasureOverride/ArrangeOverride самой WrapPanel, только с заданными размерами элемента. Зачем всё это нужно, если это всё уже реализовано у WrapPanel (и реализация там, надо сказать, не очень проста). Плюс у WrapPanel есть свойства ItemWidth и ItemHeight, которые как раз определяют фиксированный размер элемента панели, и они используются внутри реализации MeasureOverride/ArrangeOverride, и они помечены флагом FrameworkPropertyMetadataOptions.AffectsMeasure. Поэтому я сделал проще: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
и в XAML сделал так: Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
Но вариант с SharedSizeGroup мне нравится больше - остановлюсь на нём. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2019, 13:41 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Событие Loaded, это не совсем то, что вы себе представляете, за время жизни объекта оно может быть вызвано более 1 раза. Выше вы писали, что хотите, чисто в академических целях разобраться как работает макетирование в WPF (Measure\Arrange), по этому ваша отсылка в существующим реализациям, мне не совсем понятна. Используйте WrapPanel, я не против. Если поищите в интернетах, даже найдете реализацию этой панели с поддержкой виртуализации ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2019, 13:52 |
|
WPF: Шпаргалка для создания панели
|
|||
---|---|---|---|
#18+
Роман ответил подробно, я лишь немного общих словWinterGraveyardЧто тут нужно переопределить? MeasureOverride? ArrangeOverride?Переопределять нужно оба метода в любом случае, потому что в базовом классе стоят заглушки WinterGraveyardв каком из методов (и как) мне задать для всех остальных элементов аналогичную ширину и высоту?НЕ НАДО переопределять ширину и высоту дочерних элементов! Ты так зациклишься - будет бесконечное переизмерение и переразмещение. Задача панели не задавать размер элемента, а размещать эти элементы, то есть выделить им координаты и пространство в соответствии с твоей логикой. А задача элемента - разместиться внутри этого пространства (например с HorizontalAlignment=Stretch) WinterGraveyardWrapPanel (и реализация там, надо сказать, не очень проста)У Метью МакДональда в книжке есть реализация WrapPanel с возможностью добавления принудительного конца строки. Ничего сложного в коде панели у него нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2019, 15:50 |
|
|
start [/forum/topic.php?fid=21&msg=39774907&tid=1440338]: |
0ms |
get settings: |
11ms |
get forum list: |
13ms |
check forum access: |
5ms |
check topic access: |
5ms |
track hit: |
32ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
49ms |
get tp. blocked users: |
1ms |
others: | 12ms |
total: | 140ms |
0 / 0 |