你知道Labels + TextBoxes数据输入布局更动态的网格吗?

时间:2009-06-24 07:34:52

标签: wpf

我的LOB应用已经加载屏幕,这些屏幕包含标签和文本框列,并排。

我想在Grid和WrapPanel布局之间找到一些东西 - 当页面/窗口足够宽时,标签+文本框对重新组织成多个列。想象:

缩小窗口Layou:

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

广泛的窗口布局:

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

使用网格很简单,因为标签列宽度可以是“自动”...但是随着窗口宽度增加/减少,很难动态设置列数,因为它不需要在每个标签上使用样式/文本框。

使用WrapPanel可实现多列效果,但每个Label的宽度都不同。我更喜欢一种解决方案,不涉及通过样式或绑定来限制所有标签的Width属性。

您是否知道此问题的优雅解决方案,或者您是否遇到过专门提供此功能的开源/第三方面板控件?

我尊重Stack-Overflow社区,并肯定会对任何合理的建议进行投票。

1 个答案:

答案 0 :(得分:0)

我找到了 的答案,这似乎在提高XAML可读性和可维护性方面有几个好处。

通过为TextBox和Combobox创建ControlTemplates,您可以轻松地在列上使用SharedSizeGroup建立网格,这有助于保持标签的宽度相同。我创建的控件模板使用逻辑控件的Tag属性来确定模板创建的视觉中标签的文本。

考虑以下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控件可以完美地完成这项工作),但是为了快速修复,这很有效。