将插入符号/光标位置设置为字符串值 WPF 文本框的末尾

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2888907/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:47:26  来源:igfitidea点击:

Set the caret/cursor position to the end of the string value WPF textbox

wpftextboxcursorcaretcursor-position

提问by Zamboni

I am try to set the caret/cursor position to the endof the string value in my WPF textbox when I open my window for the first time. I use the FocusManager to set the focus on my textbox when my window opens.

当我第一次打开窗口时,我尝试将插入符号/光标位置设置为WPF 文本框中字符串值的末尾。当我的窗口打开时,我使用 FocusManager 将焦点设置在我的文本框上。

Nothing seems to work. Any ideas?

似乎没有任何效果。有任何想法吗?

Note, I am using the MVVM pattern, and I included only a portion of the XAML from my code.

请注意,我使用的是 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>

回答by wpfwannabe

You can set the caret position using CaretIndexproperty of a TextBox. Please bear in mind that this is not a DependencyProperty. Nevertheless, you may still set it in XAML like this:

您可以使用 a 的CaretIndex属性设置插入符号位置TextBox。请记住,这不是DependencyProperty. 尽管如此,您仍然可以像这样在 XAML 中设置它:

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

Please remember to set CaretIndexafterTextproperty or else it will not work. Thus it probably won't work if you bind to Textlike in your example. In that case, simply use code-behind like this.

请记住CaretIndexText属性之后设置否则它将不起作用。因此,如果您Text在示例中绑定到like,它可能无法工作。在这种情况下,只需像这样使用代码隐藏。

NumberOfDigits.CaretIndex = NumberOfDigits.Text.Length;

回答by Louis

You may also create a Behavior, which, while still being code-behind, has the advantage of being reusable.

您还可以创建一个 Behavior,它虽然仍然是代码隐藏的,但具有可重用的优势。

Example of a simple behavior class, using the focus event of the textbox:

一个简单的行为类示例,使用文本框的焦点事件:

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;
    }
}    

Then, in your XAML, you attach the behavior like so:

然后,在您的 XAML 中,您附加如下行为:

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

回答by Michael Ceranski

This worked for me. I am also using the MVVM pattern. However, my purpose for using a MMVM is to make unit testing possible and to make it easier to update my UI (loosely coupled). I don't see myself unit testing the position of the cursor so I don't mind resorting to the code behind for this simple task.

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

    public ExpeditingLogView()
    {
        InitializeComponent();

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

回答by molbalga

If your textbox (WinForms) is multiline with a vertical scrollbar you can try this:

如果您的文本框 (WinForms) 是带有垂直滚动条的多行文本框,您可以尝试以下操作:

textbox1.Select(textbox1.Text.Length-1, 1);
textbox1.ScrollToCaret();

Note: In WPF .ScrollToCaret() is not a member of TextBox.

注意:在 WPF 中 .ScrollToCaret() 不是 TextBox 的成员。

回答by andreikashin

In case of multiline TextBoxsetting cursor is not enough. Try this:

在多行TextBox设置光标的情况下是不够的。尝试这个:

NumberOfDigits.ScrollToEnd();

回答by Andrey the Autobot

In WPF if line is long enough it is important also to scroll to the end of the line. So i'm using the following lines:

在 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);

but read this caution (for me it's fine - probably already fixed): TextBox ScrollToHorizontalOffset will not scroll after text is long enough

但请阅读此警告(对我来说很好 - 可能已经修复): TextBox ScrollToHorizo​​ntalOffset 在文本足够长后不会滚动

回答by Flourick

None of the answers here worked for me. I am using binding for the TextBox and needed to move the caret right after the window poped up. This did it for me:

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

public MyWindow()
{
    InitializeComponent();

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

Similar to Ceranski answer. Instead of adding to the Loaded we add to ContentRendered.

类似于 Ceranski 的回答。我们没有添加到 Loaded,而是添加到 ContentRendered。

回答by Al Banna Techno logy

@Louis solution will not work if textboxused in template binding or any type of lazy bindings or lazy value assignments

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

So if the textboxused for example in Datagrid cell as a template that solution will need for tiny modification to work

因此,如果textbox例如在 Datagrid 单元格中用作模板,该解决方案将需要进行微小的修改才能工作

and that is subscribing to text changed event

那就是订阅文本更改事件

 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;
        }
    }