WPF Richtextbox FontFace / FontSize - PullRequest
6 голосов
/ 23 марта 2009

В настоящее время я пытаюсь создать некоторые базовые функции текстового процессора в проекте WPF. Я использую RichTextBox и знаю обо всех командах Editing (ToggleBold, ToggleItalic ... и т. Д.). То, на чем я застрял, это позволяет пользователю изменять размер шрифта и шрифта, как в MS Office, где значение изменяется только для выделенного текста, а если нет выделенного текста, то значение будет изменяться для текущей позиции каретки. Я придумал приличный объем кода, чтобы заставить его работать, но у меня проблемы с отсутствием выделенного текста. Вот что я делаю для RichTextBox.Selection.

TextSelection text = richTextBox.Selection;
if (text.IsEmpty)
{
    //doing this will change the entire word that the current caret position
    //is on which is not the desire/expected result.
    text.ApplyPropertyValue(RichTextBox.FontSizeProperty, value);
}
else
    //This works as expected.
    text.ApplyPropertyValue(RichTextBox.FontSizeProperty, value);

Итак, мой вопрос: как мне это сделать? Есть ли лучший / более удобный способ сделать это? Одна мысль, которая у меня возникла, заключалась в том, что мне нужно было вставить новый Inline в абзац, но я не мог понять, как это сделать. Любая помощь приветствуется. Спасибо.

Ответы [ 7 ]

2 голосов
/ 23 декабря 2009

У меня точно такая же проблема. Я был в состоянии использовать TextElement.FontSizeProperty, как сказал Бендевей. Однако, это все еще не работало совершенно правильно. Просматривая проект по ссылке ниже, я обнаружил, что все еще делаю что-то не так. Я не устанавливал фокус обратно на RichTextBox ... что автору проекта ниже не нужно было делать, потому что они использовали комбинированный список с лентой. С помощью обычного комбинированного списка после выбора шрифта он действительно меняет шрифт выделения в RichTextBox, но отвлекает внимание от RTB. Когда вы снова нажимаете на RTB, чтобы получить фокус и начинаете печатать, у вас появляется новый объект выделения, и в этом случае шрифт возвращается к шрифту по умолчанию самого RTB.

http://www.codeplex.com/WPFRichEditorLibrary

1 голос
/ 22 октября 2014

Я решил это следующим образом:

TextRange r = new TextRange(richtextbox.Selection.Start, richtextbox.Selection.End);
r.ApplyPropertyValue(TextElement.FontSizeProperty, value);
1 голос
/ 28 мая 2013

@ sub-jp правильно, вам нужно установить фокус обратно на RichTextBox, иначе вы измените свойства одного выбора, но когда вы вернетесь к текстовому полю, вы получите новый выделение существующим шрифтом. Попробуйте изменить свой код так:

TextSelection text = richTextBox.Selection;

richTextBox.Focus();

text.ApplyPropertyValue(RichTextBox.FontSizeProperty, value);

... и тогда он должен работать правильно, когда выделен текст, а когда нет.

В качестве альтернативы , как предлагается здесь , вы можете установить свойство Focusable ComboBox на False, чтобы полностью избежать этой проблемы.

1 голос
/ 23 марта 2009

Попробуйте это

var range = new TextRange( richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd );
range.ApplyPropertyValue( TextElement.FontSizeProperty, value );
0 голосов
/ 27 июля 2017

Это легко решить, если вы обрабатываете OnTextInput.

protected override void OnTextInput(TextCompositionEventArgs e)
{
    TextRange range = new TextRange(this.Selection.Start, this.Selection.End);
    // Doesn't matter whether the selection is empty or not, it should be 
    // replaced with something new, and with the right formatting
    range.Text = e.Text;

    // Now nothing else would get affected...
    range.ApplyPropertyValue(TextElement.FontFamilyProperty, value);
    this.CaretPosition = range.End;
    e.Handled = true; // You might not need this line :)
}

EDIT: Установка CaretPosition в конец TextRange может привести к неправильному выравниванию Caret. Мой RichTextBox имеет много BaselineAlignment настроек, так что, возможно, именно это и послужило причиной моего. Но, если вы когда-либо испытывали забавные Caret скачки или падения, попробуйте проверить, находится ли Caret в конце Paragraph каждый раз, прежде чем правильно установить CaretPosition. Примерно так будет работать:

TextRange test = new TextRange(range.End, range.End.Paragraph.ContentEnd);
bool IsAtEnd = test.IsEmpty || String.IsNullOrEmpty(test.Text) || test.Text == "\r\n";

// Now we know whether the Caret is still in the middle of the text or not
// This part corrects the Caret glitch! :)
if (!IsAtEnd)
    this.CaretPosition = range.End;
else
    this.CaretPosition = range.Start.GetNextContextPosition(LogicalDirection.Forward);

Я знаю, что мой ответ опоздал и все, но надеюсь, что я помог кому-то еще. Ура!

0 голосов
/ 09 июня 2015

Проблема в том, что вы должны установить focus обратно в Rich Textbox после выбора нового FontFamily или Font Size:

//When Font Size is changed
private void rbngFontSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        rtbMain.Focus(); // This part is what fixes the issue, just make sure it is set before ApplyPropertyValue method.

        try
        {
            ApplyPropertyValueToSelectedText(TextElement.FontSizeProperty, e.AddedItems[0]);
        }
        catch { };
    }

//When FontFamily is changed
private void rbngFontFamily_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        FontFamily editValue = (FontFamily)e.AddedItems[0];

        rtbMain.Focus(); // This part is what fixes the issue, just make sure it is set before ApplyPropertyValue method.

        ApplyPropertyValueToSelectedText(TextElement.FontFamilyProperty, editValue);            

    }
0 голосов
/ 17 ноября 2010

У меня была похожая проблема, если я вас правильно понимаю. Я попытался найти тонну различных ответов, которые были близки, но не совсем помогли мне. Моя проблема заключалась в том, что смена шрифта работала нормально для текста, который был явно выбран, но если не было выделенного текста и размер шрифта был изменен, следующий набранный текст вернется к стандартному размеру шрифта. Вот что я наконец-то понял, попробуй и дай знать, сработало ли это для кого-то еще:

    public static void SetFontSize(RichTextBox target, double value)
    {
        // Make sure we have a richtextbox.
        if (target == null)
            return;

        // Make sure we have a selection. Should have one even if there is no text selected.
        if (target.Selection != null)
        {
            // Check whether there is text selected or just sitting at cursor
            if (target.Selection.IsEmpty)
            {
                // Check to see if we are at the start of the textbox and nothing has been added yet
                if (target.Selection.Start.Paragraph == null)
                {
                    // Add a new paragraph object to the richtextbox with the fontsize
                    Paragraph p = new Paragraph();
                    p.FontSize = value;
                    target.Document.Blocks.Add(p);
                }
                else
                {
                    // Get current position of cursor
                    TextPointer curCaret = target.CaretPosition;
                    // Get the current block object that the cursor is in
                    Block curBlock = target.Document.Blocks.Where
                        (x => x.ContentStart.CompareTo(curCaret) == -1 && x.ContentEnd.CompareTo(curCaret) == 1).FirstOrDefault();
                    if (curBlock != null)
                    {
                        Paragraph curParagraph = curBlock as Paragraph;
                        // Create a new run object with the fontsize, and add it to the current block
                        Run newRun = new Run();
                        newRun.FontSize = value;
                        curParagraph.Inlines.Add(newRun);
                        // Reset the cursor into the new block. 
                        // If we don't do this, the font size will default again when you start typing.
                        target.CaretPosition = newRun.ElementStart;
                    }
                }
            }
            else // There is selected text, so change the fontsize of the selection
            {
                TextRange selectionTextRange = new TextRange(target.Selection.Start, target.Selection.End);
                selectionTextRange.ApplyPropertyValue(TextElement.FontSizeProperty, value);
            }
        }
        // Reset the focus onto the richtextbox after selecting the font in a toolbar etc
        target.Focus();
    }
...