у меня проблема. Я создал новый класс под названием «LetterBox», этот класс наследуется от TextBox, сейчас все работает. Но вот проблема: мне нужно событие или функция, которая «заполняет» текстовое поле.
Например: я нажимаю клавишу «T», и в текстовом поле TextBox появляется буква T. Но какое событие или функция заполняет это поле?
Я хочу изменить текстовое поле со String на свой собственный объект WordElement.
Вот мой класс LetterBox:
internal class LetterBox : TextBox
{
public static List<WordElement> Letters { get; set; } = new();
public LetterBox()
{
FontSize = 20;
KeyDown += LetterBox_KeyDown;
}
// This event wont work as expected, because the Text gets added twice
public void LetterBox_KeyDown(object sender, KeyEventArgs e)
{
// Retrieve the Key that was pressed
Key key = e.Key;
char ckey = (char)key;
WordElement we = new();
// Set the Letter in the WordElement to manipulate it later
we.SetLetter(ckey);
Letters.Add(we);
// Delete the Text to "refresh" it
Text = "";
// Put every Letter from the list back in the Text
foreach (WordElement wordElement in Letters)
{
Text += wordElement.Letter;
}
}
}
Вот мой класс WordElement:
internal class WordElement
{
public char Letter { get; private set; }
public Color Color { get; private set; } = Colors.Black;
public float Size { get; private set; } = 12;
public bool Bold { get; private set; } = false;
public bool Italic { get; private set; } = false;
public bool Underlined { get; private set; } = false;
public void SetLetter(char letter)
{
Letter = letter;
}
public void SetColor(Color color)
{
Color = color;
}
public void SetSize(float size)
{
Size = size;
}
public void SetBold(bool bold)
{
Bold = bold;
}
public void SetItalic(bool italic)
{
Italic = italic;
}
public void SetUnderlined(bool underlined)
{
Underlined = underlined;
}
}
Надеюсь, вы понимаете мою проблему и сможете мне помочь :)
P.S.: мой английский не самый лучший :P
это для более крупного проекта, над которым я работаю, этот код находится в другом решении для проверки моей идеи о собственном текстовом поле. мне нужно текстовое поле, в котором я могу раскрасить некоторые части текста, например, то, что я выбираю, может быть изменено в цвете или шрифте и т. д., но я не хочу использовать richtextbox, потому что мне не нужен формат rtf. я хочу, чтобы это было так же, как в классе элемента слова, поэтому я могу сделать что-то вроде: «Letter[3].Color», чтобы получить цвет этой буквы
Ах я вижу. но TextBox — неправильный элемент управления для выделения ext, не так ли? Он не поддерживает форматированный текст. Вам следует взглянуть на FormattedText. Это позволяет отображать текст вручную. Вы можете форматировать посимвольно. Вы можете нарисовать FormattedText
, используя DrawingContext.DrawText
. TextBox
вас точно ни к чему не приведет. Я бы не стал больше тратить на это время. Он специализируется на вводе текста. Простой текстовый ввод.
Вы также можете использовать TextBlock
и составить его, используя отформатированные Run
элементы, как если бы вы делали это в FlowDocument. Но TextBlock не предназначен для отображения больших текстов. Для более крупных текстов вы можете просмотреть FormattedText. Вы можете управлять кареткой с помощью Win32 API.
Я знаю, что не могу отображать форматированный текст с помощью стандартного TextBox, но я использовал его в этом тестовом решении для тестирования своих классов. Следующим шагом будет создание чего-то вроде текстового поля, которое может отображать форматированный текст, и пользователь может редактировать текст (это должно быть «текстовое поле»). мой более крупный проект — это инструмент для людей, которые хотят писать истории или книги, а текстовое поле или текстовое поле — это самое важное, но чтобы облегчить мне задачу в будущем, я хочу, чтобы он работал с WordElement сорт.
также я создал LetterBox, который, как я думал, смогу создать свое собственное текстовое поле с этим форматированным текстом, потому что richtextbox тоже наследуется от класса текстового поля, верно? поэтому я пытаюсь использовать этот класс для создания собственного текстового поля.
RichTextBox не наследуется от TextBox. Он наследует TextBoxBase. Это огромная разница, поскольку вся обработка текстового контейнера отсутствует. RichTextBox не использует текстовый контейнер по умолчанию, поскольку он работает с FlowDocument. Не думайте, что это будет легкая задача. Вам необходимо реализовать всю отрисовку текста и взаимодействие с ним, например, позиционирование курсора, команды клавиатуры, выделение текста, с нуля. Я не говорю, что это выходит за рамки ваших навыков (просто говорю это, чтобы не допустить неверного истолкования моих слов).
Я просто предупреждаю вас, что это не так просто, как создать подкласс «TextBox» (как вы это выразили), а затем просто заменить текстовые символы. Прежде чем вы начнете тестировать свой класс WordElement, я бы проверил, как визуализировать текст и управлять им в пользовательском текстовом контейнере. Если вам это удалось, продолжайте совершенствовать. Вы начинаете не с того конца, что, скорее всего, приведет к потере большого количества часов, потому что вы, наконец, решите выбрать стороннюю библиотеку, потому что вы застряли или перегружены усилиями, которые для этого требуются.
Установите e.Handled = true;
, чтобы подавить стандартную обработку ввода в LetterBox_KeyDown
.
Но если вы получаете результат от другого элемента управления, вы переопределите OnKeyDown
вместо подписки на событие, а затем просто не будете вызывать base.OnKeyDown();
, чтобы подавить стандартную обработку ввода.
protected override void OnKeyDown(KeyEventArgs e)
{
// Your code
}
Спасибо за ваш ответ, я просто забыл, что «e.Handled = true» подавляет стандартную обработку, но теперь это работает :)
Могу ли я спросить, чего именно вы пытаетесь достичь? Очистка всего текста при каждом вводе не очень эффективна и, скорее всего, вызовет проблемы, поскольку всегда вызывает событие TextChanged. В чем идея? Почему вы очищаете все данные только для того, чтобы добавить их обратно? Конкатенация в вашем цикле также неэффективна с точки зрения скорости и памяти.