WPF, XMAL процентный интервал вычисляется неправильно

#wpf #xaml #user-controls

#wpf #xaml #пользовательские элементы управления

Вопрос:

Короче говоря

Насколько я понимаю, используя * в xaml, вы должны получить «фиксированные» проценты. Однако даже при добавлении двух сеток к элементу управления с одинаковыми определениями строк и столбцов вычисления кажутся разными.

tl; dr

Что я хочу сделать

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

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

Мой подход

Для достижения этой цели я создал «основную» сетку для размещения трех элементов (левая сетка дизайна, центральный элемент управления для открытия средства выбора цвета и правая сетка). Я добавил центральный элемент управления, инкапсулированный сеткой, просто чтобы оставаться в соответствии с моими подходами для левой и правой стороны.

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

Проблема

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

«Решение»

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

Простая установка значения Grid.ColumnSpan="4" to Grid.ColumnSpan="3" для самой правой строки исправляет интервал, изменение значения Grid.ColumnSpan="4" to Grid.ColumnSpan="3" в самой внешней левой строке также правильно изменит интервал.

Новая проблема

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

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

Другое решение?

Я просто пошел дальше и изменил все строки на холсты с черным цветом фона. Это устраняет проблему, и все представлено правильно. Но все же я сижу здесь, не понимая, почему эта проблема возникла в первую очередь. Я хочу понять, что могло привести к изменению вычисления процентов, чтобы улучшить мои знания о проектировании пользовательских интерфейсов с помощью XAML.

However, the controls preview seems to work now, but when «consumed» by another control (meaning I’ve added that control to another control) it seems like the entire spacing is all wrong again, just as it was when I’ve used lines.

A new culprit

Upon playing around I’ve noticed when removing the textbox the spacing would be correct again, even when consumed by another control. Still, my problem here is to understand how that could be an issue even though the percentages should all be the same, leaving no room for the horizontal lines to differ.

Naturally I wondered whether the negative margin could cause the error (that is there in order for the TextBlock to move closer to the line). But with or without margin, the error still consists.

A more general question

I know, general question on best approaches and practices are not very welcomed here, but please let me ask at least about resources on how to design well written Controls with XAML. All I’ve read the past weeks helped me a great lot, and yet I seem to stumble across many problems on a regularly basis.

I cannot tell you where I’ve read this on the Microsoft docs site, but it clearly stated that one should try to avoid the use of canvases. Maybe I’ve misunderstood, however, it does seem to me like using a canvas here seems to be a cheap trick to avoid a simple problem I’ve had with the lines.

Furthermore, if anyone has any idea on how to change the controls layout in order to achieve the desired output please let me know. Thank you in advance for even taking the time to read through this.

Resources

User-control with lines

Problem: Displaying the horizontal lines slightly off

 <UserControl ...
             mc:Ignorable="d" d:DesignHeight="50"  d:DesignWidth="400"
             MinHeight="50">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="54"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <!-- left hand side grid-->
        <Grid Grid.Column="0"
              Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="1"/>
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="2*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="1"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="2*"/>
            </Grid.RowDefinitions>

            <Line Grid.Column="0" Grid.ColumnSpan="1"
                  Grid.Row="1" Grid.RowSpan="3"
                  X1="0" X2="0"
                  Y1="0" Y2="1"
                  Stroke="Black"
                  StrokeThickness="1"
                  Stretch="Uniform"
                  SnapsToDevicePixels="True"/>
            <Line Grid.Column="0" Grid.ColumnSpan="3"
                  Grid.Row="2" Grid.RowSpan="1"
                  X1="0" X2="1"
                  Y1="0" Y2="0"
                  Stroke="Black"
                  StrokeThickness="1"
                  Stretch="Uniform"
                  SnapsToDevicePixels="True"/>
            <Line Grid.Column="2" Grid.ColumnSpan="1"
                  Grid.Row="0" Grid.RowSpan="5"
                  X1="0" X2="0"
                  Y1="0" Y2="1"
                  Stroke="Black"
                  StrokeThickness="1"
                  Stretch="Uniform"
                  SnapsToDevicePixels="True"/>
        </Grid>

        <!-- middle grid -->
        <Grid Grid.Column="1"
              Grid.Row="0">
            <Canvas Margin="2, 0"
                    Background="Red"/>
        </Grid>

        <!-- right hand side grid-->
        <Grid Grid.Column="2"
              Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="1"/>
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="2*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="1"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="2*"/>
            </Grid.RowDefinitions>

            <Line Grid.Column="0" Grid.ColumnSpan="1"
                  Grid.Row="0" Grid.RowSpan="5"
                  X1="0" X2="0"
                  Y1="0" Y2="1"
                  Stroke="Black"
                  StrokeThickness="1"
                  Stretch="Uniform"
                  SnapsToDevicePixels="True"/>
            <Line Grid.Column="0" Grid.ColumnSpan="3"
                  Grid.Row="2" Grid.RowSpan="1"
                  X1="0" X2="1"
                  Y1="0" Y2="0"
                  Stroke="Black"
                  StrokeThickness="1"
                  Stretch="Uniform"
                  SnapsToDevicePixels="True"/>
            <Line Grid.Column="2" Grid.ColumnSpan="1"
                  Grid.Row="1" Grid.RowSpan="4"
                  X1="0" X2="0"
                  Y1="0" Y2="1"
                  Stroke="Black"
                  StrokeThickness="1"
                  Stretch="Uniform"
                  SnapsToDevicePixels="True"/>

            <TextBlock Grid.Column="1"
                       Grid.Row="3" Grid.RowSpan="2"
                       Text="Prefered Color"
                       FontSize="20"
                       FontFamily="Segoe UI Light"
                       Typography.Capitals="SmallCaps"
                       Foreground="Black"
                       HorizontalAlignment="Right"
                       Margin="4, -3, 4, 0"/>
        </Grid>
    </Grid>
</UserControl>
 

Пользовательский элемент управления, отображаемый в конструкторе, с отключенными горизонтальными линиями

Пользовательское управление с помощью холстов

Проблема: кажется, работает в предварительном просмотре, но будет неправильно рассчитан при добавлении в другой элемент управления

 <UserControl ...
             mc:Ignorable="d" d:DesignHeight="50"  d:DesignWidth="400"
             MinHeight="50">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="54"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <!-- left hand side grid-->
        <Grid Grid.Column="0"
              Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="1"/>
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="2*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="1"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="2*"/>
            </Grid.RowDefinitions>

            <Canvas Grid.Column="0" Grid.ColumnSpan="1"
                  Grid.Row="1" Grid.RowSpan="3"
                  Background="Black"
                  SnapsToDevicePixels="True"/>
            <Canvas Grid.Column="0" Grid.ColumnSpan="3"
                  Grid.Row="2" Grid.RowSpan="1"
                  Background="Black"
                  SnapsToDevicePixels="True"/>
            <Canvas Grid.Column="2" Grid.ColumnSpan="1"
                  Grid.Row="0" Grid.RowSpan="5"
                  Background="Black"
                  SnapsToDevicePixels="True"/>
        </Grid>

        <!-- middle grid -->
        <Grid Grid.Column="1"
              Grid.Row="0">
            <Canvas Margin="2, 0"
                    Background="Red"/>
        </Grid>

        <!-- right hand side grid-->
        <Grid Grid.Column="2"
              Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="1"/>
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="2*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="1"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="2*"/>
            </Grid.RowDefinitions>

            <Canvas Grid.Column="0" Grid.ColumnSpan="1"
                  Grid.Row="0" Grid.RowSpan="5"
                  Background="Black"
                  SnapsToDevicePixels="True"/>
            <Canvas Grid.Column="0" Grid.ColumnSpan="3"
                  Grid.Row="2" Grid.RowSpan="1"
                  Background="Black"
                  SnapsToDevicePixels="True"/>
            <Canvas Grid.Column="2" Grid.ColumnSpan="1"
                  Grid.Row="1" Grid.RowSpan="4"
                  Background="Black"
                  SnapsToDevicePixels="True"/>

            <TextBlock Grid.Column="1"
                       Grid.Row="3" Grid.RowSpan="2"
                       Text="Prefered Color"
                       FontSize="20"
                       FontFamily="Segoe UI Light"
                       Typography.Capitals="SmallCaps"
                       Foreground="Black"
                       HorizontalAlignment="Right"
                       Margin="4, 0, 4, 0"/>
        </Grid>
    </Grid>
</UserControl>
 

Пользовательское управление с холстами вместо корректно отображаемых строк в конструкторе

Пользовательский элемент управления отображается неправильно после добавления в другой элемент управления

Комментарии:

1. Чтобы вы знали, я также попытался создать единую сетку. Тем не менее, вычисления там тоже неправильные. В сетке было три определения строк с размерами *, 1, *. По какой-то странной причине строка с высотой, установленной на 1px, отображалась намного больше.

Ответ №1:

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

Поэтому не стесняйтесь добавлять ответы, и я выберу ответ, который объясняет проблему как правильный.

 <UserControl ...
             mc:Ignorable="d" d:DesignHeight="50"  d:DesignWidth="400"
             MinHeight="50">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="1"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="10"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="1"/>
            <ColumnDefinition Width="40"/>
            <ColumnDefinition Width="1"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="1"/>
        </Grid.ColumnDefinitions>

        <Button Grid.Column="3"
                Grid.Row="0" Grid.RowSpan="5"
                Margin="4,0"
                Background="Red"
                BorderThickness="0"
                Command="{Binding ColorClick}">
        </Button>

        <TextBlock Grid.Column="5"
                   Grid.Row="4" Grid.RowSpan="2"
                   Text="Prefered Color"
                   FontSize="20"
                   FontFamily="Segoe UI Light"
                   Typography.Capitals="SmallCaps"
                   Foreground="Black"
                   HorizontalAlignment="Right"
                   Margin="4, 0, 4, 0"/>

        <Canvas Grid.Column="0"
                Grid.Row="1" Grid.RowSpan="3"
                Background="Black"/>
        <Canvas Grid.Column="1"
                Grid.Row="2" Grid.RowSpan="1"
                Background="Black"/>
        <Canvas Grid.Column="2"
                Grid.Row="0" Grid.RowSpan="5"
                Background="Black"/>
        <Canvas Grid.Column="4"
                Grid.Row="0" Grid.RowSpan="5"
                Background="Black"/>
        <Canvas Grid.Column="5"
                Grid.Row="2" Grid.RowSpan="1"
                Background="Black"/>
        <Canvas Grid.Column="6"
                Grid.Row="1" Grid.RowSpan="5"
                Background="Black"/>

    </Grid>
</UserControl>