Поиск…


Вступление

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

Этот принцип дизайна снижает стоимость обслуживания макета, думая о макете по-другому.

Демонстрация проблемы и решение

Например, представьте себе экран с тремя разделами, выложенный следующим образом: Желаемая компоновка экрана

Синей коробке может быть предоставлен запас 4,4,0,0. Зеленой коробке может быть предоставлен запас 4,4,4,0. Предел фиолетового поля будет 4,4,4,4. Вот XAML: (Я использую сетку для достижения макета, но этот принцип дизайна применяется независимо от того, как вы выбираете достижение макета):

<UserControl x:Class="WpfApplication5.UserControl1HardCoded"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="2*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Border Grid.Column="0" Grid.Row="0" Margin="4,4,0,0" Background="DodgerBlue" BorderBrush="DarkBlue" BorderThickness="5"/>
    <Border Grid.Column="1" Grid.Row="0" Margin="4,4,4,0" Background="Green" BorderBrush="DarkGreen" BorderThickness="5"/>
    <Border Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Margin="4,4,4,4" Background="MediumPurple" BorderBrush="Purple" BorderThickness="5"/>
</Grid>
</UserControl>

Теперь представьте, что мы хотим изменить макет, чтобы поместить зеленую рамку слева от синего квадрата. Должно быть просто, не так ли? За исключением того, что когда мы перемещаем этот ящик, нам нужно возиться с полями. Либо мы можем изменить поля синей коробки до 0,4,4,0; или мы можем заменить синий на 4,4,4,0 и зеленый до 4,4,0,0. Вот XAML:

<UserControl x:Class="WpfApplication5.UserControl2HardCoded"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Border Grid.Column="1" Grid.Row="0" Margin="4,4,4,0" Background="DodgerBlue" BorderBrush="DarkBlue" BorderThickness="5"/>
        <Border Grid.Column="0" Grid.Row="0" Margin="4,4,0,0" Background="Green" BorderBrush="DarkGreen" BorderThickness="5"/>
        <Border Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Margin="4,4,4,4" Background="MediumPurple" BorderBrush="Purple" BorderThickness="5"/>
    </Grid>
</UserControl>

Теперь положим фиолетовый бокс наверху. Таким образом, маржа синего становится 4,0,4,4; зеленый становится 4,0,0,4.

<UserControl x:Class="WpfApplication5.UserControl3HardCoded"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="2*"/>
        </Grid.RowDefinitions>

        <Border Grid.Column="1" Grid.Row="1" Margin="4,0,4,4" Background="DodgerBlue" BorderBrush="DarkBlue" BorderThickness="5"/>
        <Border Grid.Column="0" Grid.Row="1" Margin="4,0,0,4" Background="Green" BorderBrush="DarkGreen" BorderThickness="5"/>
        <Border Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Margin="4,4,4,4" Background="MediumPurple" BorderBrush="Purple" BorderThickness="5"/>
    </Grid>
</UserControl>

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

введите описание изображения здесь

Таким образом, синяя коробка имеет поля 2,2,2,2; зеленый ящик имеет поля 2,2,2,2; фиолетовая коробка имеет поля 2,2,2,2. И в контейнере, в котором они размещены, дается прокладка (не маржа) 2,2,2,2. Вот XAML:

<UserControl x:Class="WpfApplication5.UserControl1HalfTheWhitespace"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             Padding="2,2,2,2">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Border Grid.Column="0" Grid.Row="0" Margin="2,2,2,2" Background="DodgerBlue" BorderBrush="DarkBlue" BorderThickness="5"/>
        <Border Grid.Column="1" Grid.Row="0" Margin="2,2,2,2" Background="Green" BorderBrush="DarkGreen" BorderThickness="5"/>
        <Border Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Margin="2,2,2,2" Background="MediumPurple" BorderBrush="Purple" BorderThickness="5"/>
    </Grid>
</UserControl>

Теперь давайте попробуем переместить ящики вокруг, так же, как раньше ... Давайте поместим зеленую коробку слева от синей коробки. Готово. И не нужно было менять какие-либо дополнения или поля. Вот XAML:

<UserControl x:Class="WpfApplication5.UserControl2HalfTheWhitespace"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             Padding="2,2,2,2">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Border Grid.Column="1" Grid.Row="0" Margin="2,2,2,2" Background="DodgerBlue" BorderBrush="DarkBlue" BorderThickness="5"/>
        <Border Grid.Column="0" Grid.Row="0" Margin="2,2,2,2" Background="Green" BorderBrush="DarkGreen" BorderThickness="5"/>
        <Border Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Margin="2,2,2,2" Background="MediumPurple" BorderBrush="Purple" BorderThickness="5"/>
    </Grid>
</UserControl>

Теперь положим фиолетовый бокс наверху. Готово. И не нужно было менять какие-либо дополнения или поля. Вот XAML:

<UserControl x:Class="WpfApplication5.UserControl3HalfTheWhitespace"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             Padding="2,2,2,2">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="2*"/>
        </Grid.RowDefinitions>

        <Border Grid.Column="1" Grid.Row="1" Margin="2,2,2,2" Background="DodgerBlue" BorderBrush="DarkBlue" BorderThickness="5"/>
        <Border Grid.Column="0" Grid.Row="1" Margin="2,2,2,2" Background="Green" BorderBrush="DarkGreen" BorderThickness="5"/>
        <Border Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Margin="2,2,2,2" Background="MediumPurple" BorderBrush="Purple" BorderThickness="5"/>
    </Grid>
</UserControl>

Как использовать это в реальном коде

Для того, чтобы обобщить то , что мы продемонстрировали выше: отдельные вещи содержат фиксированный запас «половинной по-пробельных», и контейнер , они проводятся в должны иметь отступы «половинной на-пробельных». Вы можете применить эти стили в своем словаре ресурсов приложений, и тогда вам даже не придется упоминать их об отдельных элементах. Вот как вы можете определить «HalfTheWhiteSpace»:

<system:Double x:Key="DefaultMarginSize">2</system:Double>
<Thickness x:Key="HalfTheWhiteSpace" Left="{StaticResource DefaultMarginSize}" Top="{StaticResource DefaultMarginSize}" Right="{StaticResource DefaultMarginSize}" Bottom="{StaticResource DefaultMarginSize}"/>

Затем я могу определить базовый стиль, чтобы основать мои другие стили элементов управления: (это также может содержать ваши стандартные шрифты FontFamily, FontSize и т. Д. И т. Д.).

<Style x:Key="BaseStyle" TargetType="{x:Type Control}">
    <Setter Property="Margin" Value="{StaticResource HalfTheWhiteSpace}"/>
</Style>

Затем я могу определить стиль по умолчанию для TextBox для использования этого поля:

<Style TargetType="TextBox" BasedOn="{StaticResource BaseStyle}"/>

Я могу делать такие вещи для DatePickers, Labels и т. Д. И т. Д. (Все, что может быть проведено в контейнере). Остерегайтесь стилизации TextBlock, как это ... этот элемент управления используется внутренне множеством элементов управления. Я предлагаю вам создать свой собственный элемент управления, который просто происходит из TextBlock. Вы можете настроить TextBlock для использования поля по умолчанию; и вы должны использовать свой TextBlock всякий раз, когда явным образом использую TextBlock в вашем XAML.

Вы можете использовать аналогичный подход для применения дополнения к общим контейнерам (например, ScrollViewer, Border и т. Д.).

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



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow