如何获取 WinUI UWP TextBox 中的当前行索引?
How to get the Current Line Index in WinUI UWP TextBox?
我知道 SelectionStart
属性 的 WinUI UWP TextBox
将 return CaretIndex
。但是,我想获得文本的确切列和行位置。在 WPF 中,GetLineFromCharacterIndex(CaretIndex)
和 TextBox.Lines[LineIndex].Length
可用于查找当前 行索引 和 列数字 分别。我怎样才能在 WinUI UWP Textbox
中实现相同的目标?
也许你可以这样做:
var text = Textbox.Text;
var lines = text.Split('\r');
...
这在过去使用 WPF 对我有用,但我从未尝试过 UWP。
这似乎也是一种解决方法,因此可能会有更好、更实用的解决方案。
试试这个方法:
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;
}
它可能需要稍作改进,但它应该能让您了解如何确定光标的当前行。
你可以在任何你想获取索引的地方调用它,例如:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
int index = GetCurrentLineIndex(sender as TextBox);
//...
}
此示例使用 MVVM 结构,但您可以将相同的概念应用于存储先前值的临时变量。
<TextBox Height="600" Width="600"
Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" AcceptsReturn="True"/>
然后我将其添加到构造函数中:
this.DataContext = this;
这不是最佳实践,如果您使用的是 MVVM,您将设置一个 ViewModel 并使用它(我这样做是为了测试目的)。
然后我创建了这样的属性:
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;
}
}
然后添加我的功能:
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;
}
如果您不使用 MVVM,只需执行此操作:
public string[] TempLines { get; set; }
...
//after the calculation code has finished
TempLines = TextBox.Split('\r');
然后你可以用 TempLines 代替 value
我知道 SelectionStart
属性 的 WinUI UWP TextBox
将 return CaretIndex
。但是,我想获得文本的确切列和行位置。在 WPF 中,GetLineFromCharacterIndex(CaretIndex)
和 TextBox.Lines[LineIndex].Length
可用于查找当前 行索引 和 列数字 分别。我怎样才能在 WinUI UWP Textbox
中实现相同的目标?
也许你可以这样做:
var text = Textbox.Text;
var lines = text.Split('\r');
...
这在过去使用 WPF 对我有用,但我从未尝试过 UWP。
这似乎也是一种解决方法,因此可能会有更好、更实用的解决方案。
试试这个方法:
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;
}
它可能需要稍作改进,但它应该能让您了解如何确定光标的当前行。
你可以在任何你想获取索引的地方调用它,例如:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
int index = GetCurrentLineIndex(sender as TextBox);
//...
}
此示例使用 MVVM 结构,但您可以将相同的概念应用于存储先前值的临时变量。
<TextBox Height="600" Width="600"
Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" AcceptsReturn="True"/>
然后我将其添加到构造函数中:
this.DataContext = this;
这不是最佳实践,如果您使用的是 MVVM,您将设置一个 ViewModel 并使用它(我这样做是为了测试目的)。
然后我创建了这样的属性:
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;
}
}
然后添加我的功能:
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;
}
如果您不使用 MVVM,只需执行此操作:
public string[] TempLines { get; set; }
...
//after the calculation code has finished
TempLines = TextBox.Split('\r');
然后你可以用 TempLines 代替 value