How to specify caret position in Mahapps Metro inputbox?

681 Views Asked by At

I am using ShowInputAsync to display an input box. Some predefined text is set with DefaultText.

MetroDialogSettings settings = new MetroDialogSettings() { DefaultText = "Some text" };
var result = await window.ShowInputAsync("Some title", "Some message", settings);

How to position the caret after the DefaultText?

Users should be able to append to this default text and having the caret before it is not really ergonomic...

1

There are 1 best solutions below

8
igorushi On BEST ANSWER

A good aproach of setting carret at the end of the TextBox described here.
All you need is to find the InputDialog's TextBox. UserControl implementing InputDialog is MahApps.Metro.Controls.Dialogs.InputDialog and the needed texbox named PART_TextBox. There are multiple posible solutions, I propose you to create Blend Behavior and attach it using style (concept take from here).

Behavior code:

public class BaseMetroDialogAdjustTextBehavior : Behavior<InputDialog>
{
    public static DependencyProperty IsAttachedProperty =
                   DependencyProperty.RegisterAttached("IsAttached", 
                   typeof(bool),
                   typeof(BaseMetroDialogAdjustTextBehavior),
                   new FrameworkPropertyMetadata(false, OnIsAttachedChanged));
    private TextBox inputTextBox;
    public static bool GetIsAttached(DependencyObject uie)
    {
        return (bool)uie.GetValue(IsAttachedProperty);
    }

    public static void SetIsAttached(DependencyObject uie, bool value)
    {
        uie.SetValue(IsAttachedProperty, value);
    }

    private static void OnIsAttachedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        UIElement element = obj as UIElement;
        if (element == null)
           return;
        {
            var behaviors = Interaction.GetBehaviors(element);
            var existingBehavior = behaviors.OfType<BaseMetroDialogAdjustTextBehavior>().FirstOrDefault();

            if ((bool)e.NewValue == false && existingBehavior != null)
            {
                behaviors.Remove(existingBehavior);
            }
            else if ((bool)e.NewValue == true && existingBehavior == null)
            {
                behaviors.Add(new BaseMetroDialogAdjustTextBehavior());
            }
        }
    }

    protected override void OnAttached()
    {
        inputTextBox = AssociatedObject.FindName("PART_TextBox") as TextBox;
        inputTextBox.GotFocus += inputTextBox_GotFocus;
    }

    protected override void OnDetaching()
    {
        inputTextBox.GotFocus -= inputTextBox_GotFocus;
    }

    void inputTextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        inputTextBox.CaretIndex = inputTextBox.Text.Length;
    }
}

In oder to attach this behavior you can place the following code in app.xaml

<Application 
...
         xmlns:Dialogs="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
         xmlns:local="clr-namespace:THE_NAMESPASE_OF_BEHAVIOR">
    <Application.Resources>
        <ResourceDictionary>
            <Style TargetType="{x:Type Dialogs:InputDialog}">
                <Style.Setters>
                    <Setter Property="local:BaseMetroDialogAdjustTextBehavior.IsAttached" Value="True"/>
                </Style.Setters>
            </Style>
        </ResourceDictionary>
    </Application.Resources>
</Application>