【问题标题】:Constrain WPF element width inside its container限制其容器内的 WPF 元素宽度
【发布时间】:2012-02-13 23:42:42
【问题描述】:

我在其他控件的网格中放置了一个模板化按钮,其中包含一些内容(图像和文本块):

<SomeControl>
   <Grid>
       <SpecialButton/>
   </Grid>
</SomeControl>

<Style TargetType="{x:Type local:SpecialButton}">>
    ...
    <Setter Property="Template">
        <Setter.Value>
        ...
            <TextBlock/>
            <TextBlock/>
        </Setter.Value>
</Style>

“SomeControl”控件的宽度是动态的——也就是说——它可以根据屏幕宽度、容器宽度等动态变化。因此我使用另一种方法来计算“SpecialButton”的宽度。
只要按钮内的文本块不比按钮本身宽“SpecialButton”的大小与它的“SomeControl”容器完美匹配。
但是,如果 TextBlock 的文本比“SpecialButton”的宽度长,“SpecialButton”的右边框就会消失,并且按钮看起来很糟糕。话虽如此,“SpecialButton”的宽度仍然限制在其容器的宽度内,尽管绘图没有得到很好的计算。
我正在尝试找到一种方法来控制 TextBlock(甚至更好的是完整网格的宽度)而不定义绝对宽度,因此“SpecialButton”仍然可以很好地绘制并忽略它的儿童溢出。像 CSS 的 {overflow:hidden} 这样的东西会很棒......
注意:
我不能允许换行,因为“SpecialButton”高度也被包含(并手动计算)。

【问题讨论】:

  • 如果你的按钮有一个最大宽度,并且你不能允许换行,你能允许截断吗?您想要的可接受和预期的最终结果是什么?您是否希望按钮继续增长直到填满容器的宽度,然后停止并截断文本?
  • 另外,如果您对答案进行投票并将其标记为此类,您可能会吸引更多人对回答您的问题感兴趣。
  • 是的,我可以允许截断,这正是我正在寻找的结果 - 文本将被截断以适应 当前 最大可用空间。

标签: wpf xaml wpf-controls


【解决方案1】:

一旦您习惯了 WPF 元素中的宽度(和高度),它就会变得非常简单。您的网格默认设置为自动宽度,这意味着它将请求父级宽度的 100%。

我通常不会设置最大尺寸,而是将我想要动态调整大小和定位的项目放在网格中,并设置网格行和列的大小。因此,如果我想占用 1/3 的可用水平空间,我可以有一个包含两列的网格,一列宽度设置为“1*”,另一列设置为“2*”(2/3 是两倍1/3 的大小),并将我的项目放在第 1 列设置为占用所有可用宽度。

在您的情况下,文本需要被截断,因为它正在尽最大努力呈现所有文本,并将按钮扩展到其容器的边界之外。内置修整功能有两种选择。 TextTrimming="CharacterEllipsis"TextTrimming="WordEllipsis" 只需将其放在您的文本块中即可。我会将文本块放在某种容器中以将它们分开。如果第一个的内容足够长,它可能会将另一个完全推到一边。

元素大小

<Window
    x:Class="MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640" Height="480">
    <Grid x:Name="LayoutRoot" DataContext="{Binding}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="2*"/>
        </Grid.ColumnDefinitions>
        <local:SomeControl Margin="8,8,8,0"/>
    </Grid>
</Window>

文本修剪

<ControlTemplate x:Key="ButtonBaseControlTemplate1" TargetType="{x:Type ButtonBase}">
    <Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding Button.IsDefaulted}" SnapsToDevicePixels="True" ThemeColor="Metallic">
        <TextBlock Text="{TemplateBinding Content}" TextTrimming="WordEllipsis" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Microsoft_Windows_Themes:ButtonChrome>
    <ControlTemplate.Triggers>
        <Trigger Property="IsKeyboardFocused" Value="True">
            <Setter Property="RenderDefaulted" TargetName="Chrome" Value="True"/>
        </Trigger>
        <Trigger Property="ToggleButton.IsChecked" Value="True">
            <Setter Property="RenderPressed" TargetName="Chrome" Value="True"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

此外,您可能还希望将文本框的工具提示设置为文本的值。如果文本被截断并且用户想查看它是什么,他们可以将鼠标悬停在按钮上并找出答案。

【讨论】:

    猜你喜欢
    • 2012-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多