2

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...

riQQ
  • 9,878
  • 7
  • 49
  • 66
Jocelyn
  • 277
  • 4
  • 21

1 Answers1

1

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>
igorushi
  • 1,855
  • 21
  • 19
  • And ***this*** is why WPF needs another good baking in the oven – Jcl Jun 23 '15 at 11:33
  • I agree this is not straightforward. – igorushi Jun 23 '15 at 11:43
  • nothing but the very basic is straightforward in WPF, everything is convoluted... by the time I realized this I was in the middle of developing a decently sized project in it and could just not easily go back. Now the code is full of things like this answer, which we'll look in a few years and wonder why the hell did we lose our time with :-) – Jcl Jun 23 '15 at 11:46
  • WPF is a bit overloaded. On the other hand, complexity is a price for flexibility. It is possible to customize a third party control even dynamically, even if it not designed for extensibility, I find this powerful. – igorushi Jun 23 '15 at 13:48
  • I agree, but then again assembler is also powerful and allows you to do anything at expense of complexity. WPF is just (IMO) half-baked, and just not that well thought of (or, never matured to the point of being so). It's not a discussion to have in stackoverflow comments though, so we'll just end this here :-) – Jcl Jun 23 '15 at 13:51
  • 1
    Btw if you compile Mahapps from source you can achieve same functionality using one line of code `PART_TextBox.GotFocus += (s,e)=>PART_TextBox.CaretIndex = PART_TextBox.Text.Length` – igorushi Jun 23 '15 at 13:51
  • Exactly what I was looking for! You taught me something, thank you! – Jocelyn Jun 24 '15 at 10:31
  • 1
    OnDetaching() method should unsubscribe instead of subscribing again: ``` inputTextBox.GotFocus -= inputTextBox_GotFocus; – Alexander Smirnov Jul 18 '18 at 11:45