要求:
这就是我希望按钮看起来的样子(请忽略造型,包装是重要部分)
我正在寻找有关如何动态文本换行的想法。
答案 0 :(得分:2)
我尝试通过编辑Button
的默认模板来实现此目的,主要是添加换行TextBlock
而不是默认ContentPresenter
,并在转换器中计算其Width
。这种方法在转换器中需要相当多的数据,但是这样做可以更简单(更好):)但它似乎仍在工作。由于默认模板中的ButtonChrome
只需像这样使用
<Button Style="{StaticResource WrappingButton}"
MinWidth="100"
Content="This button has some long text">
</Button>
在WrappingButtons
StackPanel
的屏幕截图示例
WrappingButton Style
<Style x:Key="WrappingButton" TargetType="{x:Type Button}"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<ControlTemplate.Resources>
<local:WrappingButtonWidthConverter x:Key="WrappingButtonWidthConverter"/>
</ControlTemplate.Resources>
<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding IsDefaulted}" SnapsToDevicePixels="true">
<TextBlock VerticalAlignment="Center"
FontSize="{TemplateBinding FontSize}"
FontFamily="{TemplateBinding FontFamily}"
FontStyle="{TemplateBinding FontStyle}"
FontWeight="{TemplateBinding FontWeight}"
FontStretch="{TemplateBinding FontStretch}"
LineStackingStrategy="BlockLineHeight"
TextWrapping="Wrap"
TextTrimming="WordEllipsis"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Content}">
<TextBlock.Width>
<MultiBinding Converter="{StaticResource WrappingButtonWidthConverter}">
<Binding RelativeSource="{RelativeSource Self}" Path="Text"/>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="FontFamily"/>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="FontStyle"/>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="FontWeight"/>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="FontStretch"/>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="FontSize"/>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="MinWidth"/>
</MultiBinding>
</TextBlock.Width>
</TextBlock>
</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="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<强> WrappingButtonWidthConverter 强>
public class WrappingButtonWidthConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string text = values[0].ToString();
FontFamily fontFamily = values[1] as FontFamily;
FontStyle fontStyle = (FontStyle)values[2];
FontWeight fontWeight = (FontWeight)values[3];
FontStretch fontStretch = (FontStretch)values[4];
double fontSize = (double)values[5];
double minWidth = (double)values[6];
string[] words = text.Split(new char[] {' '});
double widthSum = 0.0;
List<double> wordWidths = GetWordWidths(words, fontFamily, fontStyle, fontWeight, fontStretch, fontSize, out widthSum);
double width = 0.0;
for (int i = 0; width < (widthSum / 2.0) && i < wordWidths.Count; i++)
{
width += wordWidths[i];
}
return minWidth > 0.0 ? Math.Max(minWidth, width) : width;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
private List<double> GetWordWidths(string[] words,
FontFamily fontFamily,
FontStyle fontStyle,
FontWeight fontWeight,
FontStretch fontStretch,
double fontSize,
out double widthSum)
{
List<double> wordWidths = new List<double>();
widthSum = 0.0;
foreach (string word in words)
{
Typeface myTypeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);
FormattedText ft = new FormattedText(word + " ",
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
myTypeface,
fontSize,
Brushes.Black);
wordWidths.Add(ft.WidthIncludingTrailingWhitespace);
widthSum += ft.WidthIncludingTrailingWhitespace;
}
return wordWidths;
}
}
答案 1 :(得分:1)
由于您将文本限制为两行,我的建议是将自定义面板编写为按钮内容,将指定的文本,字体等转换为WPF FormattedText对象。然后,您可以测量它并决定在MeasureOverride和ArrangeOverride中如何布局和显示它。如果文本不适合,FormattedText甚至有一个显示...缩写的参数。要将它保持为两行,您需要先创建它,然后检查其高度以查看单行的高度。 (需要在评论中添加休息,因为StackOverflow正在抛出错误)。
答案 2 :(得分:1)
http://wpf.2000things.com/2011/07/11/339-wrapping-a-buttons-text-content-to-multiple-lines/
这让我完成了。还有这个:
<Window.Resources>
<local:Questions x:Key="theQs"/>
<Style x:Key="WrappingButton" TargetType="{x:Type Button}">
<Setter Property="FontSize" Value="10">
</Setter>
</Style>
</Window.Resources>
和此:
<Button Name="btnDef4" Grid.Row="3" Style="{StaticResource WrappingButton}" >
<TextBlock Text="{Binding ElementName=LVQuestions, Path=SelectedItem.TheDefs[3].Deftext}"
TextWrapping="Wrap"/>
</Button>
答案 3 :(得分:0)
使用RichTextBox作为按钮的内容:
RichTextBox rtb = new RichTextBox();
rtb.IsReadOnly = true;
rtb.Focusable = false;
rtb.BorderThickness = new Thickness(0);
rtb.Background = Brushes.Transparent;
rtb.AppendText("This button has some long text.");
myButton.Content = rtb;