To try to get “out of my comfort zone” (which is pretty small to begin with) in WPF I decided to try and emulate some of the UI enhancements I’ve heard about in Office 12. One of them is called “live preview” which shows you in real-time what potential changes (like increasing the font size, making something bold etc) will look like in your document as you you mouse over things. I implemented a “live preview” of the font changing. This was cool because I got to implement a font-selection dialog in WPF (creating a collection of system fonts and binding it to a dropdown list in WPF took about 5 lines of C# and 3 lines of XAML), and play with a few styles and such. In addition to this I had a look at manipulating the super-flexible WPF RichTextBox. I’m pretty sure if you didn’t care about interoperability with MSWord you could build a fully-featured word processor using this control in a few days. One challenge was that none of the WPF UI elements provide a “hover” event (the font is only supposed to update if you hover over the same item for a little while). I had to fake it (poorly) using a timer. There are a few other glaring imperfections too - for example if you “preview” a font change but then don’t actually select anything then your document DOESN’T go back to the way it was before…but hey - its a demo.
The reason the font dropdown list is so wide is because some of the names of the crazy fonts I installed to play around with this feature. There is a video of it in action also here [180 KB].
Here is the XAML (for the Dec 05 CTP):
<?Mapping XmlNamespace=“urn:JCooney.Net.SeeingIsBelieving” ClrNamespace=“SeeingIsBelieving” ?> <Window x:Class=“SeeingIsBelieving.Window1” xmlns=“http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x=“http://schemas.microsoft.com/winfx/xaml/2005" xmlns:local=“urn:JCooney.Net.SeeingIsBelieving” Title=“SeeingIsBelieving” Loaded=“mainWindowLoaded” Width=“450” Height=“200” > <Window.Resources> <local:FontNameList x:Key=“InstalledFonts”/> <DataTemplate x:Key=“FontComboTemplate”> <TextBlock Text=“{Binding}” FontFamily=“{Binding}” MouseEnter=“fontSelectionMouseEnter”></TextBlock> </DataTemplate> <LinearGradientBrush x:Key=“SelectedItemBackground” StartPoint=“0,0” EndPoint=“0,1”> <LinearGradientBrush.GradientStops> <GradientStop Color=“#e0e4ee” Offset=“0.1”/> <GradientStop Color=“#c7d1e4” Offset=“0.4”/> <GradientStop Color=“#acbbd9” Offset=“0.5”/> <GradientStop Color=“#d5dcec” Offset=“0.95”/> </LinearGradientBrush.GradientStops> </LinearGradientBrush> <Style TargetType=“{x:Type ComboBoxItem}”> <Setter Property=“BorderThickness” Value=“1” /> <Style.Triggers> <Trigger Property=“IsMouseOver” Value=“True”> <Setter Property=“Background” Value=“{StaticResource SelectedItemBackground}”/> <Setter Property=“BorderBrush” Value=“Blue”/> <Setter Property=“Foreground” Value=“Black”/> </Trigger> <Trigger Property=“IsKeyboardFocused” Value=“True”> <Setter Property=“Background” Value=“{StaticResource SelectedItemBackground}”/> <Setter Property=“BorderBrush” Value=“Blue”/> <Setter Property=“Foreground” Value=“Black”/> </Trigger> </Style.Triggers> </Style> </Window.Resources> <DockPanel LastChildFill=“True” > <DockPanel LastChildFill=“False” DockPanel.Dock=“Top”> <ComboBox DockPanel.Dock=“Right” x:Name=“fontComboBox” FontSize=“20” MouseLeave=“fontComboMouseLeave” SelectionChanged=“fontComboSelectionChanged” ItemsSource=“{StaticResource InstalledFonts}” ItemTemplate=“{StaticResource FontComboTemplate}”/> <TextBlock DockPanel.Dock=“Right”>Fonts:</TextBlock> </DockPanel> <Border BorderBrush=“Navy” CornerRadius=“5” BorderThickness=“2”> <RichTextBox x:Name=“testInput” AcceptsReturn=“True” Padding=“10,10,10,10” FontSize=“20”> <FlowDocument> <Paragraph>The quick brown fox jumps over the lazy dog.</Paragraph> </FlowDocument> </RichTextBox> </Border>
</DockPanel> </Window>
Here is the C# (also for the Dec 05 CTP)
using System; using System.Drawing; using System.Drawing.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes;namespace SeeingIsBelieving { ///
/// Interaction logic for Window1.xaml /// public partial class Window1 : Window { System.Windows.Threading.DispatcherTimer _hoverTimer = new System.Windows.Threading.DispatcherTimer(); string _fontFamilyName; public Window1() { InitializeComponent(); } void Window1_Loaded(object sender, RoutedEventArgs e) { } private void mainWindowLoaded(object sender, RoutedEventArgs e) { _hoverTimer.Interval = new TimeSpan(0, 0, 0, 2); _hoverTimer.Tick += new EventHandler(_hoverTimerTick); } void _hoverTimerTick(object sender, EventArgs e) { SetTextSelectionFont(_fontFamilyName); } private void SetTextSelectionFont(string fontFamilyName) { System.Windows.Media.FontFamily f = new System.Windows.Media.FontFamily(fontFamilyName); testInput.Selection.ApplyPropertyValue(TextElement.FontFamilyProperty, f); } private void fontSelectionMouseEnter(object sender, RoutedEventArgs e) { TextBlock t = (TextBlock)sender; _fontFamilyName = t.Text; _hoverTimer.IsEnabled = false; _hoverTimer.IsEnabled = true; } private void fontComboSelectionChanged(object sender, RoutedEventArgs e) { SetTextSelectionFont((string)fontComboBox.SelectedItem); } private void fontComboMouseLeave(object sender, RoutedEventArgs e) { _hoverTimer.IsEnabled = false; } } public class FontNameList : System.Collections.Generic.List{ public FontNameList() { using (InstalledFontCollection fonts = new InstalledFontCollection()) { foreach (System.Drawing.FontFamily f in fonts.Families) { base.Add(f.Name); } } } } }