Office12 'LivePreview' feature implemented in WPF

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.
font selection dropdown list selecting some fonts ala Office12 LivePreview

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

Comments

JosephCooney
That should be "a font-selection drop-down" not "a font-selection dialog". I would change it except .Text/FreeTextBox drops all my XAML formatting when I try to do so.
11/01/2006 4:50:00 AM