2013-12-12 44 views
6

我會跳到追逐:有沒有什麼辦法可以告訴WPF TextBlock自己衡量自己的尺寸是否在FontWeight更改時不會改變?我怎樣纔能有一個WPF TextBlock具有相同大小的所有字體的權重?

我有一個TextBlock基於風格動態改變字體的權重。該TextBlockRadioButton裏面所以很大膽,當檢查,否則正常:

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

,這裏是單選按鈕本身:

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

不幸的是,因爲我沒有使用一個固定寬度字體當字體權重改變時,TextBlock的寬度改變,並且整個單選按鈕面板相應地改變,這在視覺上震動。

+0

你可以顯示'RadioButtons'的xaml嗎? – clcto

+0

您是否在使用RadioButtons的控件模板? –

回答

4

我創建了這個變通辦法由RadioButtonFontStyle明確設置爲Bold的內容加入一個隱藏TextBlock

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

當單選按鈕選擇這種方式和可見TextBlock是大膽,寬度不會改變,因爲隱藏的TextBlock已經適當地調整了網格大小。

0

就我個人而言,我會嘗試更好地組織我的佈局,以便它們不依賴於單選按鈕的大小。也就是說,如果你堅持這樣做,那麼當你需要改變文本和/或文本時,你需要根據它的大小設置每個TextBlock的寬度,或字體家族等。爲此,您需要將Width屬性綁定到接受所有其他值的Converter。

開始,設置文本框的寬度的風格:

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

現在添加代碼的值轉換器本身(請注意,我用code posted by Clarke Kent in another StackOverflow answer要測量的文本):

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); 
    } 
} 

但是,再次,在一個真正的應用程序中,我會嘗試通過將它們放入網格或其他東西來正確解決此問題。

+0

「...把它們放在一個網格或其他東西。」這將如何工作?這正是我正在尋找的東西,但還沒有找到辦法。 – kcnygaard

0

your comment here

「......通過把它們放在一個網格或東西。」這將如何工作?這正是我正在尋找的東西,但還沒有找到辦法。

我知道這是一個老問題。儘管在問題中你沒有真正這麼說,但這個問題也沒有包含一個很好的完整說明你的場景的問題,我懷疑你有(或者更確切地說)需要記住單選按鈕組不要改變字體樣式的大小,但否則動態調整大小。爲此,我認爲你的解決方案與隱藏的TextBlock並不差。

但我要說的是,如果你能控制的單選按鈕整個集團的佈局外,然後使用網格要素之一,安排單選按鈕本身效果會更好,因爲在暗示馬克他回答。

關鍵是網格對象可以在它們的列和行上均勻分佈寬度和高度,因此可以獨立於它們標稱的期望大小來佈置單選按鈕。

例如:

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

只是爲了表現出幾種不同的方法來解決這個問題。

請注意,即使您以其他方式嘗試以某種方式動態調整單選按鈕組的大小,上述方法也可以工作。但是,如果沒有更具體的問題,我將無法說明具體的方法能夠實現這一目標。

相關問題