关于c#:WPF如何使Viewbox从StackPanel中了解其可用空间

WPF How to make a Viewbox aware of its available space from within a StackPanel

我在http://www.codeproject.com/Tips/773386/WPF-ImageButton上有一个基于Soroosh Davaee的ImageButton示例的自定义WPF控件。自定义控件将Image和TextBlock组合在Button中的水平StackPanel中。 (顺便说一句,要运行Soroosh的示例,我必须编辑解决方案属性,以便" SampleView"是启动项目,而不是" ExtendedButton"是启动项目。)

我希望TextBlock中的文本在必要时自动缩小,以避免在文本太长而无法自然地容纳在按钮中时在右侧边缘进行剪切。例如,如果我编辑Soroosh的MainWindow.xaml以使按钮文本太长而无法容纳...

1
2
3
4
5
    ...
    <EB:ImageButton Width="100" Height="30" Content="TextTooLongToFitInTheButton" Grid.Row="2"
    ...
    <EB:ImageButton Width="100" Height="30" Content="TextTooLongToFitInTheButton" Grid.Row="2"
    ...

...结果是带有剪切文本的以下按钮:

Buttons with clipped text

在研究此问题时,似乎自动收缩TextBlock内容的最简单方法是将其包装在Viewbox中:

1
2
3
<Viewbox StretchDirection="DownOnly" Stretch="Fill">
    <TextBlock ... />
</Viewbox>

DownOnly显然阻止了Viewbox放大文本以填充空间,并且Fill(与Uniform相反)似乎告诉它仅拉伸(缩小)需要缩小的尺寸(即,我的情况)。

在Soroosh的示例Generic.xaml文件中,我将TextBlock包装在这样的Viewbox中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
     <Button >
         <StackPanel Orientation="Horizontal">
             <Image Margin="2 0"
                    Source="{TemplateBinding Image}"
                    Width="{TemplateBinding ImageWidth}"
                    Height="{TemplateBinding ImageHeight}"
                    Visibility="{TemplateBinding Image,Converter={StaticResource VisibilityConvertor}}"
                    VerticalAlignment="Center"/>
I added-->   <Viewbox StretchDirection="DownOnly" Stretch="Fill">
             <TextBlock Text="{TemplateBinding Content}"
                    VerticalAlignment="Center"/>
I added-->   </Viewbox>
         </StackPanel>
     </Button>

这产生了完全相同的剪辑按钮文本。只是做实验,我试图强迫Viewbox具有固定的宽度...

1
             <Viewbox StretchDirection="DownOnly" Stretch="Fill" Width="60">

...产生了以下结果:

Viewbox with manually-sized width

...显示了Viewbox的功能,只要它能以某种方式知道它在StackPanel中的可用宽度。

我确实注意到,如果我将Viewbox包裹在整个StackPanel周围,它将成功自动缩小StackPanel的全部内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
     <Button >
         <Viewbox StretchDirection="DownOnly" Stretch="Fill" Width="60">
             <StackPanel Orientation="Horizontal">
                 <Image Margin="2 0"
                    Source="{TemplateBinding Image}"
                    Width="{TemplateBinding ImageWidth}"
                    Height="{TemplateBinding ImageHeight}"
                    Visibility="{TemplateBinding Image,Converter={StaticResource VisibilityConvertor}}"
                    VerticalAlignment="Center"/>
                 <TextBlock Text="{TemplateBinding Content}"
                    VerticalAlignment="Center"/>
             </StackPanel>
         </Viewbox>
     </Button>

...几乎产生了我想要的:

Viewbox wrapping the entire StackPanel

...但是图像和文本都缩小了,我只希望文本缩小。

我如何才能使Viewbox只包装TextBox,并从StackPanel的一个单元中知道其可用宽度(我想应该是高度)?


这是一个普遍的问题。 解决方案就是不使用StackPanel进行任何需要重新调整子控件大小的布局。 这根本不是正确的工作Panel。 而是尝试使用Grid面板,该面板将调整其子控件的大小。 StackPanel控件实际上仅对最基本的布局职责有用。尝试任何更冒险的尝试,您会发现遇到这些问题。

另一种选择是使用TextBlock.TextTrimming属性来修剪文本……您也可以将全文放入ToolTip中。