C
C#2y ago
Indeed

❔ WPF Converter Infinite call

Hi! I am trying to make a converter that makes fontsize relative to the binding by ratio the problem is that it is jumping around as seen in the picture my xaml:
<UserControl.Resources>
<converters:RelativeFontSizeConverter
x:Key="RelativeFontSizeConverter"
WhenInvalid="15" />
<converters:MathConverter x:Key="MathConverter" />
</UserControl.Resources>
<Grid Margin="14,14">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>

<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>

<TextBlock
Grid.Row="0"
d:Text="Tell Mark"
FontSize="{Binding ActualHeight, ConverterParameter='0.7', Converter={StaticResource RelativeFontSizeConverter}, RelativeSource={RelativeSource Self}}"
FontWeight="SemiBold"
Foreground="{StaticResource BrushFgDefault}"
Text="{Binding Todo.Title}"
TextTrimming="CharacterEllipsis" />

<TextBlock
Grid.Row="1"
d:Text="Tell Mark the details of the project that he has been recently included in"
FontSize="{Binding ActualHeight, ConverterParameter='0.7', Converter={StaticResource RelativeFontSizeConverter}, RelativeSource={RelativeSource Self}}"
Foreground="{StaticResource BrushFgMuted}"
Text="{Binding Todo.Description}"
TextWrapping="Wrap" />
</Grid>


<!-- scalable square button up to 80x80 -->
<Viewbox
Grid.Column="1"
MaxWidth="80"
MaxHeight="80"
VerticalAlignment="Top"
Stretch="Uniform">
...
</Viewbox>
</Grid>
</Grid>
<UserControl.Resources>
<converters:RelativeFontSizeConverter
x:Key="RelativeFontSizeConverter"
WhenInvalid="15" />
<converters:MathConverter x:Key="MathConverter" />
</UserControl.Resources>
<Grid Margin="14,14">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>

<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>

<TextBlock
Grid.Row="0"
d:Text="Tell Mark"
FontSize="{Binding ActualHeight, ConverterParameter='0.7', Converter={StaticResource RelativeFontSizeConverter}, RelativeSource={RelativeSource Self}}"
FontWeight="SemiBold"
Foreground="{StaticResource BrushFgDefault}"
Text="{Binding Todo.Title}"
TextTrimming="CharacterEllipsis" />

<TextBlock
Grid.Row="1"
d:Text="Tell Mark the details of the project that he has been recently included in"
FontSize="{Binding ActualHeight, ConverterParameter='0.7', Converter={StaticResource RelativeFontSizeConverter}, RelativeSource={RelativeSource Self}}"
Foreground="{StaticResource BrushFgMuted}"
Text="{Binding Todo.Description}"
TextWrapping="Wrap" />
</Grid>


<!-- scalable square button up to 80x80 -->
<Viewbox
Grid.Column="1"
MaxWidth="80"
MaxHeight="80"
VerticalAlignment="Top"
Stretch="Uniform">
...
</Viewbox>
</Grid>
</Grid>
16 Replies
Indeed
Indeed2y ago
converter code:
public class RelativeFontSizeConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
try {
double baseSize;
bool validBaseSize = IsDouble(value, out baseSize);

if (!validBaseSize || !IsValidNumber(baseSize)) {
throw new ArgumentException("value must be a double", nameof(value));
}

if (Ratio is not null) {
return baseSize * Ratio;
}

double ratio;
bool validRatio = IsDouble(parameter, out ratio);
if (!validRatio || !IsValidNumber(ratio)) {
throw new ArgumentException("parameter must be a double", nameof(parameter));
}

return baseSize * ratio;
}
catch {
if (WhenInvalid is not null) {
return WhenInvalid.Value;
}

throw;
}

}

private static bool IsDouble(object s, out double value) {
if (s is double d) {
value = d;
return true;
}

return double.TryParse(s.ToString(), NumberStyles.Any, NumberFormatInfo.InvariantInfo, out value);
}

private bool IsValidNumber(double num) {
return !double.IsNaN(num) && !double.IsInfinity(num) && num > 0;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}

// allows the converter to be used for different font ratios
public double? Ratio { get; set; }

//When result is zero, null or negative
public double? WhenInvalid { get; set; }
}
public class RelativeFontSizeConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
try {
double baseSize;
bool validBaseSize = IsDouble(value, out baseSize);

if (!validBaseSize || !IsValidNumber(baseSize)) {
throw new ArgumentException("value must be a double", nameof(value));
}

if (Ratio is not null) {
return baseSize * Ratio;
}

double ratio;
bool validRatio = IsDouble(parameter, out ratio);
if (!validRatio || !IsValidNumber(ratio)) {
throw new ArgumentException("parameter must be a double", nameof(parameter));
}

return baseSize * ratio;
}
catch {
if (WhenInvalid is not null) {
return WhenInvalid.Value;
}

throw;
}

}

private static bool IsDouble(object s, out double value) {
if (s is double d) {
value = d;
return true;
}

return double.TryParse(s.ToString(), NumberStyles.Any, NumberFormatInfo.InvariantInfo, out value);
}

private bool IsValidNumber(double num) {
return !double.IsNaN(num) && !double.IsInfinity(num) && num > 0;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}

// allows the converter to be used for different font ratios
public double? Ratio { get; set; }

//When result is zero, null or negative
public double? WhenInvalid { get; set; }
}
so many value checks because ActualHeight can be NaN, 0, etc. and other stuff, as such to not get errors i had to define custom values
Doombox
Doombox2y ago
Uhh... can't ViewBox stretch TextBox? Viewbox rather, with StretchDirection="DownOnly"
Indeed
Indeed2y ago
First time do i hear about strechdirection im gonna look it up rn, thank you the important for me thing is to preserve this behavior
Indeed
Indeed2y ago
(of course it would be for whole item scaling
Indeed
Indeed2y ago
sadly doesn't work
Indeed
Indeed2y ago
it scales the whole object disabling the wraping I've tried to do such thing with stretch uniform but it didnt work
Doombox
Doombox2y ago
might have to play with it myself, but generally wrapping makes calculating desired font size a lot harder
Indeed
Indeed2y ago
this seems to be working
<Viewbox
Grid.Column="0"
StretchDirection="DownOnly">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>

<TextBlock
Grid.Row="0"
Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Viewbox}}"
d:Text="Tell Mark about project's current milestones to be met and hit"
FontWeight="SemiBold"
Foreground="{StaticResource BrushFgDefault}"
Text="{Binding Todo.Title}"
TextTrimming="CharacterEllipsis" />

<TextBlock
Grid.Row="1"
Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Viewbox}}"
d:Text="Tell Mark the details of the project that he has been recently included in as such that he knows the plan"
Foreground="{StaticResource BrushFgMuted}"
Text="{Binding Todo.Description}"
TextWrapping="Wrap" />
</Grid>

</Viewbox>
<Viewbox
Grid.Column="0"
StretchDirection="DownOnly">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>

<TextBlock
Grid.Row="0"
Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Viewbox}}"
d:Text="Tell Mark about project's current milestones to be met and hit"
FontWeight="SemiBold"
Foreground="{StaticResource BrushFgDefault}"
Text="{Binding Todo.Title}"
TextTrimming="CharacterEllipsis" />

<TextBlock
Grid.Row="1"
Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Viewbox}}"
d:Text="Tell Mark the details of the project that he has been recently included in as such that he knows the plan"
Foreground="{StaticResource BrushFgMuted}"
Text="{Binding Todo.Description}"
TextWrapping="Wrap" />
</Grid>

</Viewbox>
but only in preview window, and when scaled down and then up, the content disappears
Indeed
Indeed2y ago
Indeed
Indeed2y ago
seems to happen when the description hits 4 lines
Doombox
Doombox2y ago
ah I've had this actual specific issue before with stuff disappearing when resizing as far as I can remember from the day I spent on it, I didn't find a solution and straight up re-designed my UI so binding to the size of stuff is generally a bad idea, causes more problems than it solves
Doombox
Doombox2y ago
Stack Overflow
How do I get a textblock with textwrapping to fill a viewbox
The XAML is a page with a list of items on it inside a Viewbox. The goal is to have a department name and them a paragraph of notes underneath that. I set the background of my itemscontrol to be Re...
Doombox
Doombox2y ago
there's a partial solution here, but that's about as good as you can do dynamic stuff is often a pain, generally involves rolling a custom control from the ground up if you need it to behave a very specific way I often just redesign my UX when I run into limitations rather than spend another day trying to wrestle the framework into submission
Indeed
Indeed2y ago
Thank you very much for all of your help. I too am close to redesigning it as whole, although i did have some plans like adding swipe controls that i'll have to rethink due to that as a last ditch effort i'll see into overriding viewbox's measure method to scale stuff purely based on the height of the viewbox rather than also it's width
Indeed
Indeed2y ago
I have found this great thread and I am with my whole might trying to decode it https://stackoverflow.com/questions/4542835/making-a-viewbox-scale-vertically-but-stretch-horizontally
Stack Overflow
Making a Viewbox scale vertically but stretch horizontally
I want to make a Viewbox (or something similar) that scales only its height, and then stretches its content horizontally. If I do this: <Viewbox> <StackPanel> <Button>Foo</
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server
More Posts