WPF 如何让 Viewbox 从 StackPanel 中了解其可用空间
Posted
技术标签:
【中文标题】WPF 如何让 Viewbox 从 StackPanel 中了解其可用空间【英文标题】:WPF How to make a Viewbox aware of its available space from within a StackPanel 【发布时间】:2015-06-29 14:45:35 【问题描述】:我有一个基于 http://www.codeproject.com/Tips/773386/WPF-ImageButton 的 Soroosh Davaee 的 ImageButton 示例的自定义 WPF 控件。自定义控件在 Button 内的水平 StackPanel 中组合了 Image 和 TextBlock。 (顺便说一句,要运行 Soroosh 的示例,我必须编辑解决方案属性,以便“SampleView”是启动项目,而不是“ExtendedButton”作为启动项目。)
如果文本太长而无法自然地放入按钮中,我希望 TextBlock 中的文本在必要时自动缩小,以避免在右边缘剪裁。例如,如果我编辑 Soroosh 的 MainWindow.xaml 以使按钮文本太长而无法容纳...
...
<EB:ImageButton Width="100" Height="30" Content="TextTooLongToFitInTheButton" Grid.Row="2"
...
<EB:ImageButton Width="100" Height="30" Content="TextTooLongToFitInTheButton" Grid.Row="2"
...
...结果是带有剪切文本的以下按钮:
在研究这一点时,自动收缩 TextBlock 内容的最简单方法似乎是将其包装在 Viewbox 中:
<Viewbox StretchDirection="DownOnly" Stretch="Fill">
<TextBlock ... />
</Viewbox>
DownOnly
显然阻止了 Viewbox 放大 文本以填充空间,而 Fill
(与 Uniform
相反)似乎告诉它拉伸(收缩)只有需要缩小的维度(在我的例子中就是水平维度)。
在 Soroosh 的示例 Generic.xaml 文件中,我将 TextBlock 包装在这样的 Viewbox 中:
<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 具有固定宽度...
<Viewbox StretchDirection="DownOnly" Stretch="Fill" Width="60">
...产生了这个:
...它显示了 Viewbox 的功能,如果它在 StackPanel 内时能够以某种方式知道其可用宽度。
我确实注意到,如果我将 Viewbox 包裹在整个 StackPanel 周围,它会成功地自动收缩 StackPanel 的全部内容:
<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>
...产生的结果几乎是我想要的:
...但是图像和文本都缩小了,我希望只缩小文本。
我怎样才能使仅包装文本框的视图框从 StackPanel 的单元格中知道其可用宽度(我想是高度)?
【问题讨论】:
【参考方案1】:这是一个常见问题。解决方案只是不使用StackPanel
进行任何需要重新调整子控件大小的布局。这根本不是该工作的正确Panel
。相反,请尝试使用Grid
面板,该面板将调整其子控件的大小。 StackPanel
控件实际上只适用于最基本的布局任务......尝试任何更冒险的东西,你会发现自己遇到了这些问题。
另一种选择是使用TextBlock.TextTrimming
Property 来修剪文本...您也可以将全文放入ToolTip
。
【讨论】:
同意 100%。人们倾向于过度使用StackPanel
,但它有太多的限制,这是主要的:它的潜在可用空间在其物品流动的方向上总是无限的,所以它无法告诉它的孩子他们有多少可用空间朝着那个方向。
感谢您的大开眼界。我没有意识到 StackPanels 有这样的限制。我最终使用了DockPanel
,因为它比Grid
更简单。
@phonetagger,您应该知道DockPanel
是一个相当重量级的Panel
,并且只有在您需要确切的功能时才应该使用。与DockPanel
相比,Grid Panel
的重量要轻得多,您可以使用它创建相同的显示。
@Sheridan,重量级,你是什么意思?它在哪些方面是重量级的?
重量级如代码、RAM 等,例如。较低的性能。但请忽略该评论......我把它重新放在前面:In what order are Panels the most efficient in terms of render time and performance?。以上是关于WPF 如何让 Viewbox 从 StackPanel 中了解其可用空间的主要内容,如果未能解决你的问题,请参考以下文章