IBRA
IBRA

Reputation: 1782

Wpf localization dynamic Subscript for TextBlock

I'm using MVVM pattern to bind text to TextBlock. The text is defined in database with <Subscript> tag to define when the text is Subscript. "Some<Subscript>subscript</Subscript>text."

I tried using Unicode subscripts and superscripts, but the characters appears too small, and hard to read.

I couldn't find a direct way to do this. any suggestions?

Upvotes: 1

Views: 551

Answers (2)

IBRA
IBRA

Reputation: 1782

Using Attached properties fixed my problem in the most MVVM friendly way. You get the text and add to the TextBlock Inlines as you want.

Attached property c#:

public static class TextBlockAp {
    public static readonly DependencyProperty SubscriptTextProperty = DependencyProperty.RegisterAttached(
        "SubscriptText", typeof(string), typeof(TextboxAttachedProperty), new PropertyMetadata(OnSubscriptTextPropertyChanged));

    public static string GetSubscriptText(DependencyObject obj) {
        return (string)obj.GetValue(SubscriptTextProperty);
    }

    public static void SetSubscriptText(DependencyObject obj, string value) {
        obj.SetValue(SubscriptTextProperty, value);
    }

    private static void OnSubscriptTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        try {
            var value = e.NewValue as string;
            if (String.IsNullOrEmpty(value)) return;
            var textBlock = (TextBlock)d;

            var startTag = "<Subscript>";
            var endTag = "</Subscript>";
            var subscript = String.Empty;
            if (value.Contains(startTag) && value.Contains(endTag)) {
                int index = value.IndexOf(startTag) + startTag.Length;
                subscript = value.Substring(index, value.IndexOf(endTag) - index);
            }

            var text = value.Split(new[] { startTag }, StringSplitOptions.None);
            textBlock.Inlines.Add(text[0]);
            Run run = new Run($" {subscript}") { BaselineAlignment = BaselineAlignment.Subscript, FontSize = 9 };
            textBlock.Inlines.Add(run);
        } catch (Exception ex) {
            if (ExceptionUtilities.UiPolicyException(ex)) throw;
        }
    }
}

xaml

<TextBlock ap:TextBlockAp.SubscriptText="{Binding MyProperty}" />

It needs more refactoring to work correctly, but it's a start.

Upvotes: 0

Mark
Mark

Reputation: 317

When you know that there is a subscription Tag you may use several Runs within your TextBlock.

<TextBlock>
   <Run />
   <Run />
</TextBlock>

I think you do not know the exact position of the subscripted text, right? So, why not just analyze your input and creating a new Run programatically? The Runs with the normal text have another size than Runs with subscripted text.

If you need help with adding Runs programatically just have a look at this StackOverflow post: How to assign a Run to a text property, programmatically?

I know this is not the best way in MVVM to define XAML controls in your ViewModel, but thats the fastest way to reach better legibility.

Upvotes: 1

Related Questions