2013-12-12 20 views
6

Tôi sẽ nhảy theo đuổi: Có cách nào để nói cho WPF TextBlock để đo chính nó sao cho kích thước của nó không thay đổi khi thay đổi FontWeight của nó?Làm cách nào để có một TextFlock WPF có cùng kích thước cho tất cả các trọng số phông chữ?

Tôi có một số TextBlock thay đổi trọng số phông chữ theo kiểu động. Các TextBlock là bên trong một RadioButton vì thế nó là Bold khi kiểm tra, bình thường khác:

<Style x:Key="BoldWhenChecked" TargetType="RadioButton"> 
    <Style.Triggers> 
     <Trigger Property="IsChecked" Value="True"> 
      <Setter Property="TextElement.FontWeight" Value="Bold" /> 
     </Trigger> 
    </Style.Triggers> 
</Style 

và đây là các nút radio tự:

<StackPanel Orientation="Horizontal"> 
    <RadioButton Style="{StaticResource BoldWhenChecked}"> 
     <TextBlock Text="Item 1" /> 
    </RadioButton> 
    <RadioButton Style="{StaticResource BoldWhenChecked}"> 
     <TextBlock Text="Item 2" /> 
    </RadioButton> 
    <RadioButton Style="{StaticResource BoldWhenChecked}"> 
     <TextBlock Text="Item 3" /> 
    </RadioButton> 
    etc... 
</StackPanel> 

Thật không may, kể từ khi tôi không sử dụng một phông chữ cố định chiều rộng chiều rộng của các thay đổi TextBlock khi thay đổi trọng lượng phông chữ và toàn bộ bảng điều khiển của các nút radio thay đổi tương ứng, điều này sẽ làm sáng tỏ.

+0

Bạn có thể hiển thị xaml cho 'RadioButtons' không? – clcto

+0

Bạn có đang sử dụng mẫu điều khiển cho RadioButton không? –

Trả lời

4

Tôi tạo ra một công việc xung quanh cho điều này bằng cách thêm một ẩn TextBlock trong nội dung của RadioButton với nó FontStyle thiết lập một cách rõ ràng để Bold:

<RadioButton Style="{StaticResource BoldWhenChecked}"> 
    <Grid> 
     <TextBlock Text="Item 1" /> 
     <TextBlock Text="Item 1" FontStyle="Bold" Visibility="Hidden" /> 
    </Grid> 
</RadioButton> 

Bằng cách đó khi RadioButton được chọn và có thể nhìn thấy TextBlock là được in đậm, chiều rộng không thay đổi vì ẩn TextBlock đã kích thước lưới phù hợp.

0

Cá nhân tôi cố gắng sắp xếp bố cục của mình tốt hơn để chúng không phụ thuộc vào kích thước của nút radio. Điều đó nói rằng, nếu bạn hoàn toàn nhấn mạnh vào việc làm theo cách này thì bạn sẽ cần phải thiết lập chiều rộng của mỗi TextBlock theo kích thước của nó khi Bold, và theo cách đó sẽ làm cho nó cập nhật nếu bạn cần thay đổi văn bản và/hoặc phông chữ gia đình vv Để làm điều đó bạn sẽ cần phải ràng buộc các tài sản chiều rộng để một chuyển đổi chấp nhận tất cả những giá trị khác.

Bắt đầu với một phong cách mà bộ chiều rộng của hộp văn bản:

<Style TargetType="{x:Type TextBlock}"> 
     <Setter Property="Width"> 
      <Setter.Value> 
       <MultiBinding Converter="{StaticResource TextToWidthConverter}"> 
        <Binding Path="Text" RelativeSource="{RelativeSource Self}" UpdateSourceTrigger="PropertyChanged"/> 
        <Binding Path="FontFamily" RelativeSource="{RelativeSource Self}" UpdateSourceTrigger="PropertyChanged"/> 
        <Binding Path="FontStyle" RelativeSource="{RelativeSource Self}" UpdateSourceTrigger="PropertyChanged"/> 
        <Binding Path="FontStretch" RelativeSource="{RelativeSource Self}" UpdateSourceTrigger="PropertyChanged"/> 
        <Binding Path="FontSize" RelativeSource="{RelativeSource Self}" UpdateSourceTrigger="PropertyChanged"/> 
       </MultiBinding> 
      </Setter.Value> 
     </Setter> 
    </Style> 

Bây giờ thêm mã cho bộ chuyển đổi giá trị bản thân (lưu ý rằng tôi đang sử dụng code posted by Clarke Kent in another StackOverflow answer để đo văn bản):

public class TextToWidthConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     var text = values[0] as String; 
     var fontFamily = values[1] as FontFamily; 
     var fontStyle = (FontStyle)values[2]; 
     var fontStretch = (FontStretch)values[3]; 
     var fontSize = (Double)values[4]; 
     var size = MeasureText(text, fontFamily, fontStyle, FontWeights.Bold, fontStretch, fontSize); 
     return size.Width; 
    } 

    public object[] ConvertBack(object values, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 

    /// <summary> 
    /// Get the required height and width of the specified text. Uses Glyph's 
    /// </summary> 
    public static Size MeasureText(string text, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, double fontSize) 
    { 
     Typeface typeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch); 
     GlyphTypeface glyphTypeface; 

     if (!typeface.TryGetGlyphTypeface(out glyphTypeface)) 
     { 
      return MeasureTextSize(text, fontFamily, fontStyle, fontWeight, fontStretch, fontSize); 
     } 

     double totalWidth = 0; 
     double height = 0; 

     for (int n = 0; n < text.Length; n++) 
     { 
      ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[text[n]]; 

      double width = glyphTypeface.AdvanceWidths[glyphIndex] * fontSize; 

      double glyphHeight = glyphTypeface.AdvanceHeights[glyphIndex] * fontSize; 

      if (glyphHeight > height) 
      { 
       height = glyphHeight; 
      } 

      totalWidth += width; 
     } 

     return new Size(totalWidth, height); 
    } 

    /// <summary> 
    /// Get the required height and width of the specified text. Uses FortammedText 
    /// </summary> 
    public static Size MeasureTextSize(string text, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, double fontSize) 
    { 
     FormattedText ft = new FormattedText(text, 
              CultureInfo.CurrentCulture, 
              FlowDirection.LeftToRight, 
              new Typeface(fontFamily, fontStyle, fontWeight, fontStretch), 
              fontSize, 
              Brushes.Black); 
     return new Size(ft.Width, ft.Height); 
    } 
} 

Nhưng một lần nữa, trong một ứng dụng thực sự tôi sẽ cố gắng giải quyết điều này đúng cách bằng cách đặt chúng vào lưới hoặc thứ gì đó.

+0

"... bằng cách đặt chúng vào lưới hoặc thứ gì đó." Làm thế nào mà sẽ làm việc? Đó sẽ là chính xác những gì tôi đang tìm kiếm nhưng không tìm ra cách để làm điều đó. – kcnygaard

0

Từ your comment here:

"... bằng cách đặt chúng trong một mạng lưới hoặc một cái gì đó." Làm thế nào mà sẽ làm việc? Đó sẽ là chính xác những gì tôi đang tìm kiếm nhưng không tìm ra cách để làm điều đó.

Tôi biết đây là câu hỏi cũ. Và trong khi bạn không thực sự nói như vậy trong câu hỏi, cũng không phải câu hỏi bao gồm một tốt, Minimal, Complete, Verifiable example minh họa đầy đủ kịch bản của bạn, tôi nghi ngờ rằng bạn có (hoặc đúng hơn là có) một số cần lưu ý khi nhóm nút radio không thay đổi kích thước khi thay đổi kiểu phông chữ, nhưng làm bằng cách nào đó thay đổi kích thước động. Vì mục đích đó, tôi nghĩ rằng công việc của bạn xung quanh với các ẩn TextBlock không phải là xấu.Tuy nhiên, tôi sẽ nói rằng nếu bạn có thể kiểm soát bố cục của các nút radio toàn bộ nhóm của các nút radio bên ngoài, sau đó sử dụng một trong các thành phần lưới để sắp xếp các nút radio sẽ tốt hơn, như được gợi ý bởi Mark trong câu trả lời.

Điều quan trọng là các đối tượng lưới có thể phân phối chiều rộng và chiều cao đồng đều trên cột và hàng của chúng và do đó có thể bố trí các nút radio độc lập với kích thước mong muốn danh nghĩa của chúng.

Ví dụ:

<Window x:Class="TestSO20556328BoldRadioButtons.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 

    <Window.Resources> 
    <p:Style x:Key="BoldWhenChecked" TargetType="RadioButton"> 
     <p:Style.Triggers> 
     <Trigger Property="IsChecked" Value="True"> 
      <Setter Property="TextElement.FontWeight" Value="Bold" /> 
     </Trigger> 
     </p:Style.Triggers> 
    </p:Style> 
    </Window.Resources> 

    <StackPanel> 
    <UniformGrid Columns="3"> 
     <RadioButton Style="{StaticResource BoldWhenChecked}"> 
     <TextBlock Text="Item 1" /> 
     </RadioButton> 
     <RadioButton Style="{StaticResource BoldWhenChecked}"> 
     <TextBlock Text="Item 2" /> 
     </RadioButton> 
     <RadioButton Style="{StaticResource BoldWhenChecked}"> 
     <TextBlock Text="Item 3" /> 
     </RadioButton> 
    </UniformGrid> 

    <Grid> 
     <Grid.ColumnDefinitions> 
     <ColumnDefinition/> 
     <ColumnDefinition/> 
     <ColumnDefinition/> 
     </Grid.ColumnDefinitions> 
     <RadioButton Style="{StaticResource BoldWhenChecked}"> 
     <TextBlock Text="Item 1" /> 
     </RadioButton> 
     <RadioButton Style="{StaticResource BoldWhenChecked}" Grid.Column="1"> 
     <TextBlock Text="Item 2" /> 
     </RadioButton> 
     <RadioButton Style="{StaticResource BoldWhenChecked}" Grid.Column="2"> 
     <TextBlock Text="Item 3" /> 
     </RadioButton> 
    </Grid> 
    </StackPanel> 
</Window> 

Chỉ cần để hiển thị một vài cách khác nhau để tiếp cận vấn đề.

Lưu ý rằng ở trên có thể hoạt động ngay cả khi bạn đang cố gắng kích thước nhóm nút radio theo cách động bằng cách nào đó. Nhưng nếu không có thêm chi tiết cụ thể trong câu hỏi, tôi sẽ không thể nói cách tiếp cận cụ thể nào sẽ đạt được mục tiêu đó.

Các vấn đề liên quan