Кто-нибудь знает алгоритм, используемый для определения размера столбцов Grid с охватом ячеек? (WPF) - PullRequest
2 голосов
/ 07 апреля 2009

Использовать элемент управления WPF Grid легко, когда ваши дочерние элементы всегда содержатся в одной ячейке сетки (т. Е. Нет разделения на столбцы / строки). Столбец с фиксированной шириной остается запрошенной фиксированной шириной, а автоматический столбец действительно будет иметь размер, равный ширине самой широкой ячейки в столбце. Звездные столбцы разделяют любое оставшееся пространство в соответствии с их относительными звездными значениями. В мире все просто.

Но как только у вас есть ячейка, которая охватывает два или более столбцов, ширина столбцов становится более сложной для вычисления и действительно кажется нелогичной. Вот тривиальный пример того, что я имею в виду. Мы можем определить два столбца с первым как auto, а второй с фиксированным значением 30 пикселей.

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>

Теперь мы определяем кнопку, которая охватывает оба столбца и имеет ширину 80 пикселей. (На моем компьютере с настройками шрифта и темы и т. Д.)

<Button Grid.ColumnSpan="2" Content="QWERTYUIOP"/>

Нам нужно распределить кнопку шириной 80 пикселей по двум охватывающим столбцам. Учитывая, что для второго столбца установлено значение 30, я ожидаю, что 30 будет выделено для этого столбца, а оставшиеся 50 перейдут в первый столбец. Поскольку первый столбец является автоматическим, кажется, что это очевидно.

Но нет. Если вы попробуете это на практике, вы обнаружите, что первый столбец равен 0 пикселям, а второй столбец стал полными 80. Даже если этот второй столбец определен как фиксированный и поэтому не должен увеличиваться, он растягивается на всю ширину. кнопки. Может быть, я что-то здесь упускаю, но это не кажется мне очень логичным.

Так что к моему актуальному вопросу. Есть ли полное описание логики, используемой элементом управления Grid для выполнения этих вычислений, чтобы я мог полностью понять, как это работает? Я искал в MSDN и Google и не нашел ничего, что бы описывало, как охватывающие элементы влияют на ширину столбцов.

Ответы [ 3 ]

5 голосов
/ 30 апреля 2009

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

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

Тест 1:

<Grid Height="300" Width="300">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="..."/>
        <ColumnDefinition Width="..."/>
        <ColumnDefinition Width="..."/>
    </Grid.ColumnDefinitions>
    <Button Grid.ColumnSpan="2" Content="QWERTYUIOP"/>
</Grid>

Сетка 300 X 300 с контроллером шириной 80 пикселей. Сетка состоит из трех столбцов, а контрольные области охватывают столбцы 0 и 1:

30  , auto, *    - column 0 - 80,  column 1 - 0,  column 2 - 220
auto, auto, *    - column 0 - 40,  column 1 - 40, column 2 - 220
auto, 30  , *    - column 0 - 0,   column 1 - 80, column 2 - 220
*   , 30  , *    - column 0 - 135, column 1 - 30, column 2 - 135
*   , 30  , 26*  - column 0 - 10,  column 1 - 30, column 2 - 260
*   , auto, *    - column 0 - 150, column 1 - 0,  column 2 - 150
*   , auto, 30*  - column 0 - 10,  column 1 - 0,  column 2 - 290
30  , 30  , *    - column 0 - 30,  column 1 - 30, column 2 - 240
*   , *   , 28*  - column 0 - 10,  column 1 - 10, column 2 - 280

Итак, из этого я могу придумать ряд правил:

  1. Если элемент охватывает ячейку автоматического размера и ячейку не автоматического размера, ячейка автоматического размера будет иметь размер 0
  2. Если элемент охватывает фиксированную ячейку и автоматическую ячейку, то ширина фиксированной ячейки увеличится до минимума, который может содержать весь объект
  3. Если элемент охватывает ячейку * размера и ячейку автоматического размера, тогда ячейка * размера будет иметь ожидаемый размер
  4. Если элемент охватывает две ячейки автоматического размера, они будут расширяться, чтобы соответствовать объекту и иметь одинаковую ширину
  5. Если элемент охватывает ячейки, в которых нет автоматической ячейки, то ячейки будут иметь ожидаемый размер

Тест 2:

<Grid ShowGridLines="True" Height="300" Width="300">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="..."/>
        <ColumnDefinition Width="..."/>
        <ColumnDefinition Width="..."/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Button Grid.ColumnSpan="2" Content="QWERTYUIOP"/>
    <Button Grid.Row="1" Grid.Column="1" Content="QWERTYUIOP"/>
</Grid>

Сетка 300 X 300 с 3 столбцами, в которых размещены один элемент управления шириной 80 пикселей, столбцы 0 и 2 в строке 0 и второй элемент управления шириной 80 пикселей только в столбце 1 строки 1

30  , auto, *    - column 0 - 30,  column 1 - 80, column 2 - 190
auto, auto, *    - column 0 - 0,   column 1 - 80, column 2 - 220
auto, 30  , *    - column 0 - 0,   column 1 - 80, column 2 - 220 (*)
*   , 30  , *    - column 0 - 135, column 1 - 30, column 2 - 135
*   , 30  , 26*  - column 0 - 10,  column 1 - 30, column 2 - 260
*   , auto, *    - column 0 - 110, column 1 - 80, column 2 - 110
*   , auto, 30*  - column 0 - 7,   column 1 - 80, column 2 - 213
30  , 30  , *    - column 0 - 30,  column 1 - 30, column 2 - 240
*   , *   , 28*  - column 0 - 10,  column 1 - 10, column 2 - 280

(*) Это не совсем то, что происходит. Столбец 1 имеет размер 80, но рисует только часть элемента без охвата. В качестве элементов я использовал кнопки, а хром непокрытой кнопки заполнил первый столбец шириной 80 пикселей, но текст был обрезан до размера 30 пикселей. В основном это было полностью прикручено.

Из этого теста я могу добавить еще два правила:

  1. Если в промежутке используется автоматический столбец и может получить его размер откуда-то, он будет вести себя как ожидалось
  2. Если в столбце используется автоматический столбец и он не может получить его размер откуда-то еще, тогда система измерения будет повреждена и может привести к повреждению графики.

Итак, я думаю, мы можем объединить эти правила в одну всеобъемлющую философию:

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

Не стесняйтесь поднимать ошибку в Microsoft, но так как теперь это определенное поведение элемента управления сеткой, я думаю, что мы застряли с ним на протяжении всего срока службы WPF.

0 голосов
/ 01 октября 2009

Вот как это делается:

  • Если requiredSize (childelement.DesiredSize) соответствует предпочтительному размеру диапазона (диапазона). RequestedSize распределяется в соответствии со следующей логикой:

    • автоопределения не будут участвовать в распространении; они будут иметь минимальный размер, только если установлены.
    • для всех неавтоматических определений запрашиваемый размер распределяется поровну между ними; без превышения предпочтительного размера каждого.
  • если требуется, размер больше, чем предпочитаемый размер, но вписывается в максимальный размер диапазона. RequestedSize распределяется в соответствии со следующей логикой:

    • для всех неавтоматических определений запрашиваемый размер распределяется поровну между ними; без превышения превышения максимального размера каждого.

    • остаток от шага выше равномерно распределяется между автоматическими определениями.

  • Если требуется, размер больше максимального размера диапазона. RequestedSize распределяется поровну между всеми определениями следующим образом:

    • если экви-размер меньше максимального значения maxSizes.

      • в этом случае размер распределяется таким образом, что меньшие определения растут быстрее, чем большие.

        • , если экви-размер больше или равен максимуму максимальных размеров.
      • все определения получат равный размер как их минимальные размеры.

0 голосов
/ 07 апреля 2009

Не знаю, есть ли где-нибудь полное описание где-нибудь на паутине ..

Я знаю, что Авто означает, что он спросит, как ребенок контролирует, какого размера он хочет быть. Звездочка (*) означает, что он займет всю оставшуюся комнату ...

Редактировать: Мгновенное обновление .. Ширина (ColumnDefinition) и Высота (RowDefinition) являются структурами GridLength:

GridLength на MSDN

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...