Знаете ли вы о более динамичной сетке для макетов ввода данных Labels + TextBoxes? - PullRequest
0 голосов
/ 24 июня 2009

В моем приложении LOB загружается экранов со столбцами меток и текстовых полей рядом друг с другом.

Я хочу достичь чего-то промежуточного между макетом Grid и WrapPanel - когда, когда страница / окно достаточно широки, пары метка + текстовое поле реорганизуются в несколько столбцов. Представьте себе:

Узкие окна Layou:

Label            | TextBox
Looooong Label   | TextBox
Label            | TextBox
Label            | TextBox

Схема широкого окна:

Label            | TextBox      | Looooong Label   | TextBox
Label            | TextBox      | Label            | TextBox

Использовать сетку достаточно просто, поскольку ширина столбцов меток может быть «Авто» ... но тогда трудно динамически устанавливать количество столбцов при увеличении / уменьшении ширины окна, так как для каждого ярлыка требуется стиль /textbox.

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

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

Я уважаю сообщество Stack-Overflow и обязательно проголосую за любые разумные предложения.

1 Ответ

0 голосов
/ 24 июня 2009

Я нашел и ответ, который, по-видимому, имеет несколько преимуществ в плане улучшения читаемости и удобства сопровождения XAML.

Создав ControlTemplates для TextBox и Combobox, вы можете легко установить сетку с SharedSizeGroup на столбцы, что помогает поддерживать одинаковую ширину надписей. Созданный шаблон элемента управления использует свойство Tag элемента управления Logical для определения текста для метки в визуальном элементе, созданном шаблоном.

Рассмотрим следующий XAML, который создает два текстовых поля, оба привязаны к данным для базового бизнес-объекта:

<WrapPanel Orientation="Horizontal" Grid.IsSharedSizeScope="True">

    <TextBox Tag="On Hand:"
                     Text="{Binding Path=Product.StockOnHand}"
                     Template="{StaticResource LabeledTextBoxTemplate}"
                     IsReadOnly="True"
                     ToolTip="" />

    <TextBox    Tag="On Order:"
                        Text="{Binding Path=Product.StockOnOrder}"
                        Template="{StaticResource LabeledTextBoxTemplate}"
                        IsReadOnly="True"
                        ToolTip="" />

</WrapPanel>

Коробки находятся внутри панели переноса, где SharedSizeGroup имеет значение true. Это позволяет сеткам (которые создают шаблоны элементов управления) обмениваться информацией о ширине столбца. Поскольку текстовые поля находятся внутри WrapPanel, они будут использовать как можно большую ширину перед переносом на следующую строку.

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

<!--Style and ControlTemplates to support aligned, labeled text boxes and combo boxes.-->
<Style TargetType="Grid"
             x:Key="LabelledDataGridStyle">
    <Setter Property="Margin"
                    Value="0,0,12,4" />
</Style>

<Style TargetType="ColumnDefinition"
             x:Key="LabelingGridThirdColumnStyle">
    <Setter Property="Width"
                    Value="150" />
    <Style.Triggers>
        <DataTrigger  Binding="{Binding Path=ItemWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=WrapPanel,AncestorLevel=1}}"
                                    Value="{x:Null}">
            <Setter Property="Width"
                            Value="Auto" />
            <Setter Property="SharedSizeGroup"
                            Value="C" />
        </DataTrigger>
    </Style.Triggers>
</Style>

<ControlTemplate TargetType="TextBox" x:Key="LabeledTextBoxTemplate">
    <Grid Style="{StaticResource LabelledDataGridStyle}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="A" Width="Auto" />
            <ColumnDefinition Style="{StaticResource LabelingGridThirdColumnStyle}" />
        </Grid.ColumnDefinitions>

        <TextBlock Text="{Binding Path=Tag,RelativeSource={RelativeSource TemplatedParent}}"
                             VerticalAlignment="Top"
                             Margin="0,4,8,0"
                             HorizontalAlignment="Left" />

        <TextBox Text="{Binding Path=Text,RelativeSource={RelativeSource TemplatedParent}}"
                    TextAlignment="{Binding Path=TextAlignment,RelativeSource={RelativeSource TemplatedParent}}"
                    Style="{Binding Path=Style,RelativeSource={RelativeSource TemplatedParent}}"
                    Background="{Binding Path=Background,RelativeSource={RelativeSource TemplatedParent}}"
                    ToolTip="{Binding Path=ToolTip,RelativeSource={RelativeSource TemplatedParent}}"
                    ContextMenu="{Binding Path=ContextMenu,RelativeSource={RelativeSource TemplatedParent}}"
                    MinWidth="100"
                    Grid.Column="1" />

    </Grid>

</ControlTemplate>

Он не идеален (элемент управления Panel, выполняющий эту работу, был бы идеальным), но для быстрого исправления это прекрасно работает.

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