Personally I'd try to organize my layouts better so that they weren't dependent on the size of the radio buttons. That said, if you absolutely insist on doing it this way then you'll need to set the width of each TextBlock according to its size when Bold, and in a way that will cause it to update if you need to change the text and/or font family etc. To do that you'll need to bind the Width property to a Converter which accepts all those other values.
Start with a style that sets the width of the textbox:
<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>
Now add the code for the value converter itself (note that I'm using code posted by Clarke Kent in another StackOverflow answer to measure the text):
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);
}
}
But again, in a real app I'd try to solve this properly by putting them in a grid or something.
RadioButtons
? – Ensconce