将插入号/光标位置设置为字符串值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>

Answers:


104

您可以使用的CaretIndex属性设置插入符号的位置TextBox。请记住,这不是一个DependencyProperty。不过,您仍然可以像这样在XAML中进行设置:

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

请记住设置CaretIndex 后置 Text属性,否则它将不起作用。因此,如果您Text像示例中那样进行绑定,则可能无法正常工作。在这种情况下,只需像这样使用后台代码。

NumberOfDigits.CaretIndex = NumberOfDigits.Text.Length;

2
是的,我尝试绑定到CaretIndex,但失败了。将您的代码添加到“窗口加载的事件”中的代码后面,效果很好。谢谢。
Zamboni

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 2014年

5

这对我有用。我也在使用MVVM模式。但是,我使用MMVM的目的是使单元测试成为可能,并使更新UI(松散耦合)更加容易。我没有看到自己对光标的位置进行单元测试,所以我不介意为这个简单的任务使用背后的代码。

    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 ScrollToHorizo​​ntalOffset将不会滚动


1

这里没有答案对我有用。我正在为TextBox使用绑定,并且需要在窗口弹出后立即移动插入符号。这为我做到了:

public MyWindow()
{
    InitializeComponent();

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

类似于Ceranski的答案。而不是添加到Loaded中,而是添加到ContentRendered中。


1

如果textbox在模板绑定或任何类型的惰性绑定或惰性值分配中使用@Louis解决方案将不起作用

因此,如果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;
        }
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.