2011-07-28 37 views
5

Yêu cầu:Làm thế nào để tạo một nút Wrapping trong WPF

  • Phải hỗ trợ tài sản MinWidth
  • thể hiển thị văn bản trên chỉ có một hoặc hai dòng. Không thể quấn đến 3 hoặc nhiều hơn.
  • nên làm nút càng nhỏ càng tốt trong khi tôn trọng MinWidth
  • Văn bản có thể quấn chỉ vào khoảng trống
  • Không thể chỉ định chiều rộng. Nút sẽ tiếp tục tăng theo chiều ngang.

Dưới đây là những gì tôi muốn các nút để trông giống như (Bỏ qua các phong cách xin vui lòng, các gói là một phần quan trọng)

enter image description here

Tôi đang tìm kiếm ý tưởng về làm thế nào để làm cho văn bản quấn động.

Trả lời

1

Vì bạn đã giới hạn văn bản thành hai dòng, đề xuất của tôi là viết bảng tùy chỉnh làm nội dung nút chuyển văn bản, phông chữ, v.v. thành đối tượng WPF FormattedText. Sau đó, bạn có thể đo lường và quyết định cách bạn muốn bố cục và hiển thị trong MeasureOverride và ArrangeOverride. FormattedText thậm chí có một tham số để hiển thị một chữ viết tắt ... nếu văn bản không phù hợp. Để giữ nó thành hai dòng, trước tiên bạn muốn tạo nó, sau đó kiểm tra chiều cao của nó để xem những gì một dòng là chiều cao. (cần phải thêm phần còn lại trong các ý kiến ​​như StackOverflow là tung ra lỗi).

+0

Sau đó, bạn có thể thiết lập MaxTextWidth của nó với chiều rộng nút, sau đó kiểm tra ft.Height một lần nữa. Nếu nó cao hơn 2x Chiều cao ban đầu, bạn có nhiều hơn 2 dòng và muốn đặt MaxHeight thành khoảng 2x Chiều cao ban đầu. –

+0

Tôi sẽ chụp ảnh đó và cho bạn biết cách hoạt động. Cảm ơn ý tưởng! –

+0

Tôi đã thực hiện gần như điều này chính xác với nó, vì vậy nếu nó không làm việc cho bạn cho tôi biết. Tôi chỉ cần đăng trong ý kiến ​​như SO ngày hôm nay là tung ra lỗi khi tôi thực hiện bất cứ điều gì nhưng bài viết ngắn. –

2

Tôi đã cố gắng đạt được điều này bằng cách chỉnh sửa mẫu mặc định cho Button, chủ yếu là thêm gói TextBlock thay vì mặc định ContentPresenter và tính Width trong trình chuyển đổi. Cách tiếp cận này cần khá nhiều dữ liệu trong trình chuyển đổi, mặc dù có nhiều cách dễ dàng hơn (và tốt hơn) để làm điều này nhưng dường như nó vẫn hoạt động. Nó cần một tham chiếu đến PresentationFramework.AeroButtonChrome trong mẫu mặc định

Chỉ cần sử dụng nó như mẫu Ảnh chụp màn hình

<Button Style="{StaticResource WrappingButton}" 
     MinWidth="100" 
     Content="This button has some long text"> 
</Button> 

enter image description here
này với 3 WrappingButtons trong một 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; 
    } 
} 
0

Sử dụng một RichTextBox như nội dung của nút của bạn:

  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; 
1

http://wpf.2000things.com/2011/07/11/339-wrapping-a-buttons-text-content-to-multiple-lines/

này đã nhận nó làm cho tôi.Ngoài ra điều này:

<Window.Resources> 
     <local:Questions x:Key="theQs"/> 
     <Style x:Key="WrappingButton" TargetType="{x:Type Button}"> 
      <Setter Property="FontSize" Value="10"> 

      </Setter> 
     </Style> 
    </Window.Resources> 

và điều này:

<Button Name="btnDef4" Grid.Row="3" Style="{StaticResource WrappingButton}" > 
       <TextBlock Text="{Binding ElementName=LVQuestions, Path=SelectedItem.TheDefs[3].Deftext}" 
       TextWrapping="Wrap"/> 
      </Button> 
Các vấn đề liên quan