Displaying FontFamily in Combobox
Asked Answered
W

3

11

My goal is to manipulate the text-styles of my application via DependencyProperties. I got a diagram in which the texts are to be manipulated in size, fontfamily, color, etc. So I'd like to use an interface similar to a rich text editor like Word.

I'm using this code in my TextStyleVM http://shevaspace.blogspot.com/2006/12/i-have-some-fun-with-formattedtext_14.html

So I have a FontFamilyProperty and a Getter and Setter for it:

        public static DependencyProperty FontFamilyProperty =
            DependencyProperty.Register(
                "FontFamily",
                typeof(FontFamily),
                typeof(OutlinedText),
                new FrameworkPropertyMetadata(
                   SystemFonts.MessageFontFamily,
                   FrameworkPropertyMetadataOptions.AffectsRender |
                   FrameworkPropertyMetadataOptions.AffectsMeasure),
                      new ValidateValueCallback(IsValidFontFamily)); 

  public FontFamily FontFamily
    {
        get { return (FontFamily)base.GetValue(FontFamilyProperty); }
        set { base.SetValue(FontFamilyProperty, value); }
    }

Then there is a ToStyle method, which sets the style for the labels of the diagram, which are to be manipulated:

        Style style = new Style();
        Binding fontFamilyBinding = new Binding("FontFamily");
        fontFamilyBinding.Source = this;
        Setter fontFamilySetter = new Setter();
        fontFamilySetter.Property = TextBlock.FontFamilyProperty;
        fontFamilySetter.Value = fontFamilyBinding;
        style.Setters.Add(fontFamilySetter);

        return style;

Now this works for a TextBox. The textbox displays the current FontFamily, and if I enter a new, valid FontFamily like Arial into the textbox the FontFamily of the labels are changed.

However, what I'd like to have is a combobox, which displays the SystemFonts and where I can choose one FontFamily for my labels. However, the binding doesn't seem to work. Neither the system fonts nor the current fonts of the labels are displayed. The combobox is just empty.

This is my xaml:

            <r:RibbonLabel Content="FontFamily" />
            <!--these do not work-->
            <r:RibbonComboBox SelectedItem="{Binding FontFamily}"/>
            <r:RibbonComboBox ItemsSource="{Binding FontFamily}"/>
            <!--this works-->
            <r:RibbonTextBox Text="{Binding FontFamily}"/>

Now, I assume I have to set a different Setter for a ComboBox in the ToStyle Method. But I have no clue, which one. Maybe someting like this:

            fontFamilySetter.Property = ComboBox.ItemSource;

However, if I set that Property, the TextBox still works. So is this the wrong place to start at? I'd also be grateful if someone could hint me to some documentation about using these Style-, Setter-, Binding-key-words, which are used in the ToStyle method, since this is somebody elses code I'm working with.

West answered 1/6, 2010 at 13:22 Comment(0)
A
20

ItemsSource here expects a collection; e.g. Fonts.SystemFontFamilies

<ComboBox ItemsSource="{Binding Source={x:Static Fonts.SystemFontFamilies}}"/>

Actually, here's a very nice link covering font selection:

http://www.hanselman.com/blog/LearningWPFWithBabySmashCustomerFeedbackAndAWPFFontComboBox.aspx

Scott Hanselman even shows how to render each font item in combobox with it's own font family.


Added per OP comment.

Here's an example of binding to dependency property. Property is named "MyFontFamily" to avoid collision with existing Window's property. Sorry, no Ribbon controls (I have bare 3.5 sp1).

Window1.xaml

<Window
    x:Class="SimpleWpf.Window1"
    x:Name="ThisWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel Orientation="Vertical">
        <ComboBox
            SelectedItem="{Binding MyFontFamily, ElementName=ThisWindow}"
            ItemsSource="{Binding Source={x:Static Fonts.SystemFontFamilies}}"/>
        <TextBlock
            Text="Lazy dog jumper"
            FontFamily="{Binding MyFontFamily, ElementName=ThisWindow}"
            FontSize="24"/>
    </StackPanel>
</Window>

Window1.xaml.cs

public partial class Window1 : Window
{
    // ...

    public static readonly DependencyProperty MyFontFamilyProperty =
        DependencyProperty.Register("MyFontFamily",
        typeof(FontFamily), typeof(Window1), new UIPropertyMetadata(null));
}
Aga answered 1/6, 2010 at 15:34 Comment(3)
This works of course, but this doesn't supply any way to modify my FontFamilyProperty. Or in other words: How do I bind this ComboBox to my DependencyProperty named FontFamilyProperty? If I set SelectedValue or SelectedItem to FontFamily I get invalid cast exceptions: "System.Windows.Media.FontFamily" cannot be cast to "Microsoft.Windows.Controls.Ribbon.RibbonComboBoxItem"West
Hi Torsten; I've added an example of dp binding. Doesn't look like there are any issues with it unless you want to do something really unusual.Aga
Thanks for your avid support. I migrated my code to the Fluent Ribbon and there your example works. I have some minor changes in there though, however it is based on your idea: 1. I had to set Mode=TwoWay on the SelectedItem Binding 2. I used FrameworkPropertyMetadata on my DP (see shevaspace.blogspot.com link in my startpost), the UIPropertyMetadata works as well, though, I reckon. I really appreciate your help.West
C
7

A just in Xaml solution with fonts sorted in alphabetical order:

<Window x:Class="WpfFontsComboBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        Height="350" Width="525">
    <Window.Resources>
        <CollectionViewSource x:Key="SortedFontsCollection" Source="{Binding Source={x:Static Fonts.SystemFontFamilies}}" >
            <CollectionViewSource.SortDescriptions>
                <ComponentModel:SortDescription PropertyName="Source" />
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
    </Window.Resources>
    <StackPanel>
        <Label Content="42" FontFamily="{Binding ElementName=comboBoxFonts, Path=SelectedItem}" />
        <ComboBox x:Name="comboBoxFonts" ItemsSource="{Binding Source={StaticResource SortedFontsCollection}}" />
    </StackPanel>
</Window>

enter image description here enter image description here

Culpepper answered 2/4, 2015 at 7:21 Comment(0)
G
3

A great Font Combobox for WPF can be found here:

CodeProject.com: A XAML-Only Font ComboBox

It is pure XAML, can be just copied/pasted and even sorts the fonts properly. The article also describes nicely all the gotchas encountered and how to solve them.

Gove answered 5/9, 2013 at 7:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.