Now that we have several complex WPF applications in production, one of our users is demanding a zoom feature because he is having trouble reading some of the text. The incident went to one of our less experienced developers who promptly added a ScaleTransform to the base window that all our applications use. Personally, I would have bought the user some reading glasses, but that's just me.
The result of the ScaleTransform is not brilliant. It is unpredictable and produces undesirable results on most of the screens. We are not going to implement it. I suggested that the user really wants us to increase the font size. We've been pretty good at using styles consistently, so I decided to see how hard it would be to alter our styles and bind font sizes. Our buttons sizes are fixed, so the text can be clipped as it increases in size. I added some intelligence via a converter to prevent clipping.
This is what I came up with. It demonstrates a ViewBox, the simple ScaleTransform technique and the FontSize technique. The ScaleTransform solution has the advantage of being much simpler. The FontSize solution works better. The ViewBox is also simple but does not work well for pages with a lot of controls because they tend to start large and can't get much bigger. It's written using VisualStudio 2022 and C#.
Start a new WPF C# project called ScaleTransform. Add a class called Converters. The MainWindow.xaml looks like this...
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ScaleTransform"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="400">
<Window.Resources>
<local:ButtonWidthConverter x:Key="ButtonWidthConverter"/>
<local:ButtonHeightConverter x:Key="ButtonHeightConverter"/>
<local:FontSizeConverter x:Key="FontSizeConverter"/>
<sys:Decimal x:Key="HeadingFactor">1.5</sys:Decimal>
<Style TargetType="TextBlock" x:Key="Heading">
<Setter Property="FontSize" Value="{Binding WindowFontSize, Converter={StaticResource FontSizeConverter}, ConverterParameter={StaticResource HeadingFactor}}"/>
</Style>
<Style TargetType="TextBox">
<Setter Property="FontSize" Value="{Binding WindowFontSize}"/>
</Style>
<Style TargetType="Button">
<Setter Property="FontSize" Value="{Binding WindowFontSize}"/>
<Setter Property="Width" Value="{Binding WindowFontSize, Converter={StaticResource ButtonWidthConverter}}"/>
<Setter Property="Height" Value="{Binding WindowFontSize, Converter={StaticResource ButtonHeightConverter}}"/>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Viewbox>
<Grid>
<Grid.RenderTransform>
<ScaleTransform ScaleX="{Binding ZoomLevel}" ScaleY="{Binding ZoomLevel}"/>
</Grid.RenderTransform>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="200"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Style="{StaticResource Heading}" Text="Meeting Notes"/>
<TextBox Grid.Row="1" Text="The meeting was very boring and eventually everyone fell asleep" TextWrapping="Wrap"/>
<Button Grid.Row="2" Content="Save Notes"/>
</Grid>
</Viewbox>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<TextBlock Text="ScaleTransform" Margin="10" FontSize="13"/>
<Slider Width="100" Value="{Binding ZoomLevel}" Minimum="1" Maximum="5"/>
<TextBlock Text="FontSize" Margin="10" FontSize="13"/>
<Slider Width="100" Value="{Binding WindowFontSize}" Minimum="6" Maximum="20"/>
</StackPanel>
</Grid>
</Window>
The MainWindow.xaml.cs file contains a couple of properties and not much else.
namespace ScaleTransform
public partial class MainWindow : Window, INotifyPropertyChanged
private double _ZoomLevel = 1;
get { return _ZoomLevel; }
private double _WindowFontSize = 12;
get { return _WindowFontSize; }
public MainWindow()
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
if (!Object.Equals(storage, value))
storage = value;
if (PropertyChanged != null)
}
}
}
class ButtonWidthConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
Double FontSize = (Double)value;
return Math.Max(FontSize * 6, 100);
throw new NotImplementedException();
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
double FontSize = (Double)value;
throw new NotImplementedException();
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
double FontSize = (Double)value;
throw new NotImplementedException();
}
}
Moving the ScaleTransform slider results in bigger everything, but a lot of clipping.
Moving the FontSize slider instead produces a useful effect.
Resizing the window demonstrates the ViewBox feature.
No comments:
Post a Comment