wpfxamlcustom-controlsdependency-propertiesformatted-text

How to set dependency properties, AddOwner, in a simple custom control for FormattedText in WPF


I know this topic has been covered many times. I think I've studied most of them. But I can't seem to make this work with AddOwner(). I'm a newbie.

I wish to make a very simple custom control to display a FormattedText. Even though the dependency properties are called from the XAML, they are not being set and their new settings are not available in the constructor.

What am I doing wrong? (Maybe the question should be how to correctly use AddOwner() ? ).

Thank you for any help.

XAML:
<i:CustomTextBlock Grid.Row="0"  x:Name="tbc"
               Text="{Binding Text}" 
               FontSize="{Binding FontSize}" 
               FontStyle="Italic" 
               Foreground="{Binding Color}" 
               FontFamily="Segoe Script" />

C#:

   public class CustomTextBlock : FrameworkElement
   {
    public CustomTextBlock() 
    {
        FontWeight fontweight = FontWeights.Normal;
        FontStretch fontstretch = FontStretches.Normal;
        FlowDirection flowdirection = FlowDirection.LeftToRight;

        Typeface typeface = new Typeface(
         FontFamily,
         FontStyle,
         fontweight,
         fontstretch);

        FormattedText formattedText = new FormattedText(
             Text,
             System.Threading.Thread.CurrentThread.CurrentCulture,
             flowdirection,
             typeface,
             FontSize,
             Foreground);
    }

        public static readonly DependencyProperty TextProperty = 
        TextBlock.TextProperty.AddOwner(typeof(CustomTextBlock));

       public String Text
    {
        get { return (String)this.GetValue(TextProperty); }
        set { this.SetValue(TextProperty, value); }
    }

       public static readonly DependencyProperty FontSizeProperty =
        TextBlock.FontSizeProperty.AddOwner(typeof(CustomTextBlock));

    public Double FontSize
    {
        get { return (Double)this.GetValue(FontSizeProperty); }
        set { this.SetValue(FontSizeProperty, value); }
    }

    public static readonly DependencyProperty FontStyleProperty =
        TextBlock.FontStyleProperty.AddOwner(typeof(CustomTextBlock));

    public FontStyle FontStyle
    {
        get { return (FontStyle)this.GetValue(FontStyleProperty); }
        set { this.SetValue(FontStyleProperty, value); }
    }

    public static readonly DependencyProperty ForegroundProperty =
        TextBlock.ForegroundProperty.AddOwner(typeof(CustomTextBlock));

    public Brush Foreground
    {
        get { return (Brush)this.GetValue(ForegroundProperty); }
        set { this.SetValue(ForegroundProperty, value); }
    }

    public static readonly DependencyProperty FontFamilyProperty =
        TextBlock.FontFamilyProperty.AddOwner(typeof(CustomTextBlock));

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

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
     }

}

Solution

  • There is no problem with AddOwner, but the properties are set after the constructor is called. You have to use their values in the overridden OnRender method, and you may just drop the entire constructor:

    public class CustomTextBlock : FrameworkElement
    {
        // property declarations
        ...
    
        protected override void OnRender(DrawingContext drawingContext)
        {
            var typeface = new Typeface(
                FontFamily,
                FontStyle,
                FontWeights.Normal,
                FontStretches.Normal);
    
            var formattedText = new FormattedText(
                Text,
                Thread.CurrentThread.CurrentCulture,
                FlowDirection.LeftToRight,
                typeface,
                FontSize,
                Foreground);
    
            drawingContext.DrawText(formattedText, new Point());
        }
    }