2009-03-23 2 views
3

В настоящее время я пытаюсь создать некоторые основные функции текстового процессора в проекте WPF. Я использую RichTextBox и знаю все редактирующие команды (ToggleBold, ToggleItalic ... ect.). То, что я застрял, позволяет пользователю изменить шрифт и шрифт, как в MS Office, где значение изменяется только для выделенного текста и если нет выделенного текста, тогда значение изменится для текущей позиции каретки. У меня появилось приличное количество кода, чтобы заставить его работать, но у меня проблемы с выбранным текстом. Вот что я делаю для RichTextBox.Selection.WPF Richtextbox FontFace/FontSize

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 в абзац, но я не мог понять, как это сделать. Любая помощь приветствуется. Спасибо.

ответ

1

Попробуйте

var range = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd); 
range.ApplyPropertyValue(TextElement.FontSizeProperty, value); 
+0

-1. Этот код изменит шрифт для текстового поля * whole *, а не только позицию каретки. – TarkaDaal

2

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

http://www.codeplex.com/WPFRichEditorLibrary

0

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

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(); 
    } 
+1

Код не работает в следующем окне: 1. Введите текст. 2. Выберите текст в середине и измените шрифт. 3. Поместите точку ввода в середине измененного текста (без выбора). Попробуйте снова изменить шрифт. Курсор переместится в конец прогона. –

1

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

TextSelection text = richTextBox.Selection; 

richTextBox.Focus(); 

text.ApplyPropertyValue(RichTextBox.FontSizeProperty, value); 

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

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

0

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

TextRange r = new TextRange(richtextbox.Selection.Start, richtextbox.Selection.End); 
r.ApplyPropertyValue(TextElement.FontSizeProperty, value); 
0

Вопрос заключается в том, что вы должны установить фокус назад к Rich Textbox после выбора нового FontFamily или Размер шрифта:

//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

Пришло легко решить, если вы обрабатываете 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 находится в конце 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); 

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