0

I would like to create a control to behave like this:

<controls:FontIcon Code="&#xf0c7;"
                   IconStyle="Solid"
                   FontSize="25" />

Sadly I cannot seem to switch the FontFamily based on IconStyle.

public class FontIcon : TextBlock
{
    public static readonly DependencyProperty IconStyleProperty =
        DependencyProperty.Register(
            "IconStyle",
            typeof(Style),
            typeof(FontIcon),
            new PropertyMetadata(Controls.Style.Regular));

    public static readonly DependencyProperty CodeProperty =
        DependencyProperty.Register(
            "Code",
            typeof(string),
            typeof(FontIcon),
            new PropertyMetadata(null));

    public string Code
    {
        get { return (string) GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public Style IconStyle
    {
        get { return (Style) GetValue(IconStyleProperty); }
        set
        {
            SetValue(IconStyleProperty, value);
            SwitchFontFamily(value);
        }
    }

    private void SwitchFontFamily(Style style)
    {
        switch (style)
        {
            case Controls.Style.Regular:
                SetValue(FontFamilyProperty, new FontFamily(new Uri(@"pack://application:,,,//<MyClassLibsNamespace>;component/Fonts/Font Awesome 5 Pro-Regular-400.otf"), "Font Awesome 5 Pro Regular"));
                break;
            case Controls.Style.Solid:
                SetValue(FontFamilyProperty, new FontFamily(new Uri(@"pack://application:,,,//<MyClassLibsNamespace>;component/Fonts/Font Awesome 5 Pro-Solid-900.otf"), "Font Awesome 5 Pro Solid"));
                break;
            case Controls.Style.Light:
                SetValue(FontFamilyProperty, new FontFamily(new Uri(@"pack://application:,,,/<MyClassLibsNamespace>;component/Fonts/Font Awesome 5 Pro-Light-300.otf"), "Font Awesome 5 Pro Light"));
                break;
        }
    }
}

public enum Style
{
    Regular,
    Solid,
    Light
}

Why isn't it displaying my Icon ?

Edit 1

private void SwitchFontFamily(Style style)
    {
        switch (style)
        {

            case Controls.Style.Regular:
                FontFamily fromLibs = new FontFamily(new Uri("pack://application:,,,/UIToolsWPF;component/"), "./Fonts/#Font Awesome 5 Pro Regular");
                FontFamily = fromLibs;
                break;
            //case Controls.Style.Solid:
            //    FontFamily = new FontFamily(new Uri(@"pack://application:,,,/UIToolsWPF;component/Fonts/Font Awesome 5 Pro-Solid-900.otf"), "Font Awesome 5 Pro Solid");
            //    break;
            //case Controls.Style.Light:
            //    FontFamily = new FontFamily(new Uri(@"pack://application:,,,/UIToolsWPF;component/Fonts/Font Awesome 5 Pro-Light-300.otf"), "Font Awesome 5 Pro Light");
            //    break;
        }
    }


<StackPanel VerticalAlignment="Center"
            HorizontalAlignment="Center">
    <controls:FontIcon HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       FontSize="25"
                       x:Name="FontIcon"
                       Text="&#xf039;"
                       IconStyle="Regular" />
     <TextBlock Text="{Binding ElementName=FontIcon, Path=FontFamily}" />
</StackPanel>

enter image description here

Felix D.
  • 4,811
  • 8
  • 38
  • 72
  • Is the SwitchFontFamily method ever called? Be aware that there are situations where WPF bypasses the CLR wrapper of a dependency property, and directly calls SetValue. You should therefore never call anything else than GetValue and SetValue in the property wrapper. – Clemens Jul 23 '18 at 09:40
  • @Clemens so how do I set the `FontFamily` correctly ? Maybe using a Converter ? – Felix D. Jul 23 '18 at 09:43
  • By a PropertyChangedCallback of the IconStyle property, registered with PropertyMetadata. – Clemens Jul 23 '18 at 09:43
  • @Clemens I changed my code but sadly still nothing is displaying. – Felix D. Jul 23 '18 at 09:50
  • Also check if the Resource File Pack URIs are correct. They should contain a referenced assembly's name, not a namespace (as suggested by ``). Besides that, the Build Action of the font files should be set to `Resource`. – Clemens Jul 23 '18 at 10:08
  • @Clemens I checked that. I've done that correct :( – Felix D. Jul 23 '18 at 10:12
  • As a note, SwitchFontFamily doesn't need to be a static method. It could by called like `((FontIcon)dependencyObject).SwitchFontFamily((Style)dependencyPropertyChangedEventArgs.NewValue);`. It should also not use SetValue, but just `FontFamily = ...` – Clemens Jul 23 '18 at 10:12
  • It's also unclear why you declare `CodeProperty`, when the Code property wrapper uses `TextProperty`. – Clemens Jul 23 '18 at 10:18
  • @Clemens it's still not working ;/ I've also look at this https://msdn.microsoft.com/en-us/library/system.windows.media.fontfamily.aspx maybe there is an issue iwth the fontfamily file pack uri ? – Felix D. Jul 23 '18 at 10:36
  • You may also check [this](https://stackoverflow.com/q/38305239/1136211) and [this](https://stackoverflow.com/q/23108181/1136211). For me, creating a FontFamily from a font resource didn't work in code behind with a Pack URI, it worked only in XAML. – Clemens Jul 23 '18 at 10:36
  • @Clemens i managed to get it working in code when i move the font files to application: `new FontFamily(new Uri("pack://application:,,,/"), "./Fonts/#Font Awesome 5 Pro Regular")` But I still got no idea why I can't do the same when I move the files to a class lib :/ – Felix D. Jul 23 '18 at 10:54
  • Doesn't that also work with a referenced assembly like `new FontFamily(new Uri("pack://application:,,,/YourClassLib;component/"), "./Fonts/#Font Awesome 5 Pro Regular")`? – Clemens Jul 23 '18 at 10:57
  • @Clemens somehow that is not working ;/ that's just what i tried. When I debug, i can see the font being loaded, line spacing etc are correct in the loaded object. But it's not applied somehow – Felix D. Jul 23 '18 at 10:59
  • It works for me though... – Clemens Jul 23 '18 at 11:03
  • @Clemens it's resolving the resource AND rendering properly ? – Felix D. Jul 23 '18 at 11:05
  • Yes, exactly. Tried with Font Awesome 5 Free Solid – Clemens Jul 23 '18 at 11:06
  • @Clemens please see my edits in the question. What the heck am I missing ? – Felix D. Jul 23 '18 at 11:09
  • `UIToolsWPF` is the library's assembly name? – Clemens Jul 23 '18 at 11:13
  • @Clemens yes ;( – Felix D. Jul 23 '18 at 11:13
  • @Clemens got my mistake ! The name showing up in references of my app and the assemblyname-property of my UIToolsWPF Project were different ! – Felix D. Jul 23 '18 at 11:15
  • @Clemens ty so much for your time and efford ! – Felix D. Jul 23 '18 at 11:15

1 Answers1

0

In order to make this work I had to use the pattern described in here.

// The font resource reference includes the base URI reference (application directory level),
// and a relative URI reference.
myTextBlock.FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "./resources/#Pericles Light");

I used:

string fontRoot = "pack://application:,,,/<MyReferencedAssembly>;component/";
FontFamily = new FontFamily(new Uri(fontRoot), "./Fonts/#Font Awesome 5 Pro Regular");
Felix D.
  • 4,811
  • 8
  • 38
  • 72