Встановіть позицію курсора / курсору в кінець текстового поля WPF рядкового значення


75

Я намагаюся встановити позицію курсора / курсору в кінець значення рядка в моєму текстовому полі WPF, коли я вперше відкриваю своє вікно. Я використовую FocusManager, щоб встановити фокус на моє текстове поле, коли відкриється моє вікно.

Здається, нічого не працює. Будь-які ідеї?

Зауважте, я використовую шаблон MVVM, і я включив лише частину XAML зі свого коду.

<Window 
    FocusManager.FocusedElement="{Binding ElementName=NumberOfDigits}"
    Height="400" Width="800">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <TextBox Grid.Column="0" Grid.Row="0" 
                 x:Name="NumberOfDigits"
                 IsReadOnly="{Binding Path=IsRunning, Mode=TwoWay}"
                 VerticalContentAlignment="Center"
                 Text="{Binding Path=Digits, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <Button Grid.Column="0" Grid.Row="1" 
                 Margin="10,0,10,0"
                 IsDefault="True"
                 Content="Start" 
                 Command="{Binding StartCommand}"/>
    </Grid>
 </Window>

Відповіді:


104

Ви можете встановити положення каретки, використовуючи CaretIndexвластивість a TextBox. Будь ласка, майте на увазі, що це не є DependencyProperty. Тим не менш, ви все одно можете встановити його в XAML так:

<TextBox Text="123" CaretIndex="{x:Static System:Int32.MaxValue}" />

Будь ласка, не забудьте встановити CaretIndex після Text властивості, інакше це не буде працювати. Таким чином, це, мабуть, не спрацює, якщо ви прив’яжете лайк Textу вашому прикладі. У такому випадку просто використовуйте код-позаду таким чином.

NumberOfDigits.CaretIndex = NumberOfDigits.Text.Length;

2
Так, я намагався пов’язати CaretIndex, але це не вдалося. Додавання коду до коду ззаду у програмі Window Loaded Event спрацювало чудово. Дякую.
Замбоні,

26

Ви також можете створити поведінку, яка, хоча і залишається позаду коду, має перевагу багаторазового використання.

Приклад простого класу поведінки, що використовує подію focus текстового поля:

class PutCursorAtEndTextBoxBehavior: Behavior<UIElement>
{
   private TextBox _textBox;

   protected override void OnAttached()
   {
        base.OnAttached();

        _textBox = AssociatedObject as TextBox;

        if (_textBox == null)
        {
            return;
        }
        _textBox.GotFocus += TextBoxGotFocus;
   }

    protected override void OnDetaching()
    {
        if (_textBox == null)
        {
            return;
        }
        _textBox.GotFocus -= TextBoxGotFocus;

        base.OnDetaching();
    }

    private void TextBoxGotFocus(object sender, RoutedEventArgs routedEventArgs)
    {
        _textBox.CaretIndex = _textBox.Text.Length;
    }
}    

Потім у своєму XAML ви прикріплюєте поведінку так:

    <TextBox x:Name="MyTextBox" Text="{Binding Value}">
        <i:Interaction.Behaviors>
            <behaviors:PutCursorAtEndTextBoxBehavior/>
        </i:Interaction.Behaviors>
    </TextBox>

1
Це найкраще рішення. Встановлення курсору вручну - це біль у дупі.
Darkhydro

5

Це спрацювало для мене. Я також використовую шаблон MVVM. Однак моя мета використання MMVM полягає в тому, щоб зробити можливим модульне тестування та спростити оновлення мого інтерфейсу (вільно зв'язаного). Я не бачу, щоб я перевіряв позицію курсора, тому я не проти вдатися до коду, який стоїть задля цього простого завдання.

    public ExpeditingLogView()
    {
        InitializeComponent();

        this.Loaded += (sender, args) =>
        {                                
            Description.CaretIndex = Description.Text.Length;
            Description.ScrollToEnd();
            Description.Focus();
        };
    }

3

У разі багаторядкового TextBoxналаштування курсору недостатньо. Спробуйте це:

NumberOfDigits.ScrollToEnd();

Відповідь лише за кодом - це не хороші відповіді, додайте кілька рядків, щоб пояснити, в чому проблема і чому ваш код це
виправив

2

У WPF, якщо рядок досить довгий, важливо також прокрутити до кінця рядка. Отже, я використовую такі рядки:

text_Box.Text = text;
text_Box.CaretIndex = text.Length;
text_Box.ScrollToHorizontalOffset(double.MaxValue);
// or you can use this - for me works also
// text_Box.ScrollToHorizontalOffset(text_Box.GetRectFromCharacterIndex(openFileDialog.FileName.Length).Right);

але прочитайте цю обережність (для мене це добре - можливо, це вже виправлено): TextBox ScrollToHorizontalOffset не прокручуватиметься після того, як текст достатньо довгий


1

Жодна з відповідей тут не спрацювала для мене. Я використовую прив'язку для TextBox і мені потрібно було перемістити каретку відразу після появи вікна. Це зробило це для мене:

public MyWindow()
{
    InitializeComponent();

    ContentRendered += (sender, args) =>
    {
        MyTextBox.CaretIndex = MyTextBox.Text.Length;
        MyTextBox.ScrollToEnd();
        MyTextBox.Focus();
    };
}

Подібно до відповіді Черанського. Замість додавання до завантаженого ми додаємо до ContentRendered.


1

Рішення @Louis не буде працювати, якщо воно textboxвикористовується для прив'язки шаблонів або будь-якого типу лінивих прив'язок або призначення ледачих значень

Отже, якщо він textboxвикористовується, наприклад, у комірці Datagrid як шаблон, це рішення потребуватиме дрібних модифікацій для роботи

і це підписка на подію, змінену текстом

 class PutCursorAtEndTextBoxBehavior : Behavior<UIElement>
    {
        private TextBox _textBox;

        protected override void OnAttached()
        {
            base.OnAttached();

            _textBox = AssociatedObject as TextBox;

            if (_textBox == null)
            {
                return;
            }
            _textBox.GotFocus += TextBoxGotFocus;
            // to make it work with binding
            _textBox.TextChanged += TextBoxGotFocus;
        }

        protected override void OnDetaching()
        {
            if (_textBox == null)
            {
                return;
            }
            _textBox.GotFocus -= TextBoxGotFocus;
            _textBox.TextChanged -= TextBoxGotFocus;

            base.OnDetaching();
        }

        private void TextBoxGotFocus(object sender, RoutedEventArgs routedEventArgs)
        {
            _textBox.CaretIndex = _textBox.Text.Length;
        }
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.