Sé que la propiedad SelectionStart de WinUI UWP TextBox devolverá CaretIndex . Pero quiero obtener la posición exacta de columna y línea de texto. En WPF , GetLineFromCharacterIndex(CaretIndex) y TextBox.Lines[LineIndex].Length podrían usarse para encontrar el índice de línea actual y el número de columna , respectivamente. ¿Cómo puedo lograr lo mismo en WinUI UWP Textbox ?
Prueba este método:
public static int GetCurrentLineIndex(TextBox textBox) { int caretIndex = textBox.SelectionStart; if (caretIndex == 0) return 0; string[] lines = textBox.Text?.Split('\r') ?? Array.Empty<string>(); int offset = 0; for (int i = 0; i < lines.Length; i++) { string line = lines[i]; offset += line.Length; if (caretIndex <= offset) return i; offset++; } return 0; }Es posible que necesite una ligera mejora, pero debería darle una idea de cómo podría determinar la línea actual del cursor.
Puede llamarlo desde donde quiera obtener el índice, por ejemplo:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e) { int index = GetCurrentLineIndex(sender as TextBox); //... }Tal vez podrías hacer algo como esto:
var text = Textbox.Text; var lines = text.Split('\r'); ...Esto funcionó para mí en el pasado usando WPF pero nunca probé UWP.
Esto también parece una solución alternativa, por lo que podría haber una solución mejor y más práctica.
Este ejemplo usa la estructura MVVM pero puede aplicar los mismos conceptos con una variable temporal que almacena el valor anterior.
<TextBox Height="600" Width="600" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextWrapping="Wrap" AcceptsReturn="True"/>Luego agregué esto al constructor:
this.DataContext = this;Esta no es la mejor práctica y si estuviera usando MVVM, configuraría un ViewModel y lo usaría (lo hice con fines de prueba).
Luego creé mis propiedades así:
private int _line; public int Line { get { return _line; } set { _line = value; tb1.Text = value.ToString(); } } private int _column; public int Column { get { return _column; } set { _column = value; tb2.Text = value.ToString(); } } private string _text; public string Text { get { return _text; } set { if (_text + '\r' != value) { Line = GetLine(_text, value); Column = GetColumn(_text, value, Line); } else { Line++; Column = 0; } _text = value; } }Luego agregué mis funciones:
public int GetLine(string original, string newText) { var oLines = GenArray(original); var nLines = GenArray(newText); //set this to -1 if you want 0-based indexing int count = 0; foreach (var line in nLines) { count++; if (oLines.Length < count || line != oLines[count - 1]) { break; } } return count; } public int GetColumn(string original, string newText, int lineChanged) { var oLine = GenArray(original)[lineChanged - 1]; var nLine = GenArray(newText)[lineChanged - 1]; //set this to -1 if you want 0-based indexing int count = 0; foreach (var c in nLine) { count++; if (oLine.Length < count || c != oLine[count - 1]) { } } return count; } private string[] GenArray(string text) { string[] lines; if (text == null) { lines = new string[1] { "" }; } else if (text.Contains('\r')) { lines = text.Split('\r'); } else { lines = new string[1] { text }; } return lines; }Si no usa MVVM, simplemente haga esto:
public string[] TempLines { get; set; } ... //after the calculation code has finished TempLines = TextBox.Split('\r');Entonces puedes sustituir TempLines por valor