代码之家  ›  专栏  ›  技术社区  ›  Mark

你知道标签+文本框数据输入布局的更动态网格吗?

wpf
  •  0
  • Mark  · 技术社区  · 15 年前

    我的应用程序有 荷载 有标签和文本框列的屏幕,并排显示。

    我想在网格和包装板布局之间实现一些东西——当页面/窗口足够宽时,标签+文本框对重新组织成多个列。想象:

    窄窗布局:

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

    宽窗口布局:

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

    使用网格非常简单,因为标签列的宽度可以是“自动”…但是,当窗口宽度增加/减少时,很难动态地设置列数,因为它会在每个标签/文本框上设置样式。

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

    您知道这个问题的一个很好的解决方案吗,或者您遇到过专门提供此功能的任何开源/第三方面板控件吗?

    我尊重StackOverflow社区,并且会毫无保留地投票给任何合理的建议。

    1 回复  |  直到 13 年前
        1
  •  0
  •   Mark    15 年前

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

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

    考虑以下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。这允许网格(控件模板创建的网格)共享列宽信息。由于文本框位于包装板内,因此在包装到下一行之前,它们将使用尽可能多的宽度。

    将上述逻辑文本框呈现为网格的ControlTemplate(和Style),其中每个网格有两列,一列包含标签,另一列包含文本框,如下所示:

    <!--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>
    

    它不是完美的(完成这项工作的面板控件是理想的),但对于快速修复,这很好地工作。