简体   繁体   English

WPF Richtextbox FontFace/FontSize

[英]WPF Richtextbox FontFace/FontSize

I am currently trying to create some basic word processor features in a WPF project.我目前正在尝试在 WPF 项目中创建一些基本的文字处理器功能。 I am using a RichTextBox and am aware of all of the EditingCommands (ToggleBold, ToggleItalic...ect.).我正在使用 RichTextBox 并且知道所有的 EditingCommands(ToggleBold、ToggleItalic...等)。 The thing I am stuck on is allowing the user to change the fontsize and font face like in MS Office where the value changes for only the selected text and if there is no selected text then the value will change for the current caret position.我坚持的事情是允许用户更改字体大小和字体,就像在 MS Office 中一样,其中仅选定文本的值会更改,如果没有选定的文本,则当前插入符号 position 的值将更改。 I have come up with a decent amount of code to get this to work, but am having problems with the no selected text thing.我已经想出了相当多的代码来让它工作,但是我遇到了没有选择文本的问题。 Here is what I am doing for the RichTextBox.Selection.这是我为 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);

So my question is how should I go about doing this?所以我的问题是我应该如何做 go Is there a better/more convenient way to do this?有没有更好/更方便的方法来做到这一点? One thought I had was that I would need to insert a new Inline into the Paragraph but I couldn't figure out how to do that.我的一个想法是我需要在段落中插入一个新的内联,但我不知道该怎么做。 Any help is appreciated.任何帮助表示赞赏。 Thank you.谢谢你。

I have solved this as follows:我已经解决了这个问题:

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

I just had the exact same problem.我只是遇到了完全相同的问题。 I was able to use TextElement.FontSizeProperty as bendewey said.正如本德威所说,我能够使用 TextElement.FontSizeProperty 。 However, it still wasn't working quite right.但是,它仍然无法正常工作。 After looking through the project at the link below, I found out I was still doing something wrong.在查看下面链接的项目后,我发现我仍然做错了什么。 I wasn't setting the focus back to the RichTextBox... which the author of the project below didn't need to do because they were using a ribbon combobox.我没有将焦点重新设置到 RichTextBox ... 下面项目的作者不需要这样做,因为他们使用的是功能区 combobox。 With a regular combobox, after you select a font, it does actually change the font of the selection in the RichTextBox, but it takes the focus away from the RTB.使用常规的 combobox,在您使用 select 字体后,它确实会更改 RichTextBox 中选择的字体,但它会将焦点从 RTB 上移开。 When you click back on the RTB to get the focus and start typing, you have a new selection object, in which case the font is back to the default font of the RTB itself.当您单击 RTB 以获取焦点并开始输入时,您将获得一个新的选择 object,在这种情况下,字体将恢复为 RTB 本身的默认字体。

http://www.codeplex.com/WPFRichEditorLibrary http://www.codeplex.com/WPFRichEditorLibrary

@sub-jp is right, you need to set the focus back to the RichTextBox , otherwise you'll change the properties of one selection, but when you click back to the text box, you'll get a new selection with the existing font. @sub-jp 是对的,您需要将焦点设置回RichTextBox ,否则您将更改一个选择的属性,但是当您单击返回文本框时,您将获得一个具有现有字体的新选择. Try changing your code to be like this:尝试将您的代码更改为:

TextSelection text = richTextBox.Selection;

richTextBox.Focus();

text.ApplyPropertyValue(RichTextBox.FontSizeProperty, value);

...and then it should work correctly both when there is text highlighted, and when there is not. ...然后它应该在突出显示文本和没有突出显示的情况下都能正常工作。

Alternatively, as suggested here , you can set the Focusable property of the ComboBox to False , to avoid this issue entirely.或者,如此处所建议的,您可以将 ComboBox 的Focusable属性设置为False ,以完全避免此问题。

Try this尝试这个

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

The issue is that you must set focus back to the Rich Textbox after selecting the new FontFamily or Font Size:问题是您必须在选择新的 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);            

    }

I had a similar problem, if i am understanding you correctly.如果我理解正确的话,我遇到了类似的问题。 I tried searching a ton of various answers that were close but didn't quite work for me.我尝试搜索大量接近但对我不太有用的各种答案。 My problem was that the font change worked fine for text that was explicitly selected, but if there was no selected text, and the font size was changed, the following text typed in would revert to the default fontsize.我的问题是字体更改对于明确选择的文本效果很好,但是如果没有选定的文本,并且字体大小发生了更改,则输入的以下文本将恢复为默认字体大小。 Here is what i finally figured out, give it a shot, and let me know if it worked for anyone else:这是我终于想出来的,试一试,让我知道它是否适用于其他人:

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

It's easy to solve if you're handling OnTextInput .如果您正在处理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: Setting the CaretPosition to the end of the TextRange , might make the Caret align wrongly sometimes.编辑:将CaretPosition设置为TextRange的末尾,有时可能会使Caret对齐错误。 My RichTextBox has a lot of BaselineAlignment tweaks so that might have been what caused mine.我的RichTextBox有很多BaselineAlignment调整,所以这可能是造成我的原因。 But, if you ever experience any funny Caret jumps or sinks, try to check if the Caret is at the end of the Paragraph each time before setting the CaretPosition correctly.但是,如果您遇到任何有趣的Caret跳跃或下沉,请尝试在每次正确设置CaretPosition之前检查Caret是否位于Paragraph的末尾。 Something like this would work:像这样的东西会起作用:

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);

I know my answer is late and all, but hope I've helped someone else.我知道我的回答很晚了,但希望我帮助了别人。 Cheers!干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM