C
C#2y ago
mario12136

Move Line Up in C# TextBox like in VS

I am working on a Notepad clone and I want to create the move line up/down feature that is so common in editors. I believe in VS it is Alt+Up/Alt+Down. I was wondering how can I do this, or if someone has done it before, if you don't mind sharing your code. I might probably have to remove the current line's content and then insert it at a higher line index but what if there is already a non-empty line above? Would appreciate help on this.
2 Replies
Anton
Anton2y ago
split by new line, move the lines, join back
mario12136
mario12136OP2y ago
private void MoveLine(int direction)
{
int currentLineIndex = LineIndex - 1;
if ((currentLineIndex <= 0 && direction < 0) || (currentLineIndex == LineCount - 1 && direction > 0)) return;

int caretLine = GetLineIndexFromCharacterIndex(CaretIndex);
int caretChar = CaretIndex - GetCharacterIndexFromLineIndex(caretLine);
string[] lines = Text.Split(Environment.NewLine);
(lines[currentLineIndex], lines[currentLineIndex + direction]) =
(lines[currentLineIndex + direction], lines[currentLineIndex]);
Text = string.Join(Environment.NewLine, lines);
CaretIndex = GetCharacterIndexFromLineIndex(caretLine + direction) + caretChar;
}

private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);

if (Keyboard.IsKeyDown(Key.LeftAlt))
{
if (key == Key.Up)
{
MoveLine(-1);
e.Handled = true;
}
else if (key == Key.Down)
{
MoveLine(1);
e.Handled = true;
}
}
}
private void MoveLine(int direction)
{
int currentLineIndex = LineIndex - 1;
if ((currentLineIndex <= 0 && direction < 0) || (currentLineIndex == LineCount - 1 && direction > 0)) return;

int caretLine = GetLineIndexFromCharacterIndex(CaretIndex);
int caretChar = CaretIndex - GetCharacterIndexFromLineIndex(caretLine);
string[] lines = Text.Split(Environment.NewLine);
(lines[currentLineIndex], lines[currentLineIndex + direction]) =
(lines[currentLineIndex + direction], lines[currentLineIndex]);
Text = string.Join(Environment.NewLine, lines);
CaretIndex = GetCharacterIndexFromLineIndex(caretLine + direction) + caretChar;
}

private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);

if (Keyboard.IsKeyDown(Key.LeftAlt))
{
if (key == Key.Up)
{
MoveLine(-1);
e.Handled = true;
}
else if (key == Key.Down)
{
MoveLine(1);
e.Handled = true;
}
}
}
What do you think code-wise? I tested and it works. One annoying thing is that the caret visibly, even if ever so quickly, changes position. I took care of that with BeginChange() and EndChange()
Want results from more Discord servers?
Add your server