【问题标题】:How can I change the FontFamily in a WPF RichTextBox without modifying previous text如何在不修改先前文本的情况下更改 WPF RichTextBox 中的 FontFamily
【发布时间】:2010-11-17 05:29:46
【问题描述】:

当您使用 RichTextBox 的 FontFamily 属性时,它会更改 FlowDocument 内整个内容的 FontFamily。 与执行 EditingCommands.ToggleBold 之类的命令相同,它只更改插入符号下的单词或仅更改要写入的新文本,应该有一种方法可以对 FontsFamilies 和 Color 执行相同的操作。

【问题讨论】:

    标签: wpf fonts wpf-controls


    【解决方案1】:

    也许不是最简洁的解决方案,但您可以从 RichTextBox 继承并添加一些行为

    声明您自己的字体属性,以便您以后可以使用字体列表绑定它们

        public class CustomControl1 : RichTextBox
        {
    
    public static readonly DependencyProperty CurrentFontFamilyProperty =
                    DependencyProperty.Register("CurrentFontFamily", typeof(FontFamily), typeof  (CustomControl1), new FrameworkPropertyMetadata(new FontFamily("Tahoma"), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,new PropertyChangedCallback(OnCurrentFontChanged)));
        }
    

    覆盖 OnTextInput。您无法在 RichTextBox 上订阅此事件,内置处理 KeyDown 和 KeyUp 的冒泡,并在它们之间生成 TextInput

        protected override void OnTextInput(TextCompositionEventArgs e)
    {
            if (fontchanged)
            {
                TextPointer tp = this.CaretPosition.GetInsertionPosition(LogicalDirection.Forward);
                Run r = new Run(e.Text, tp);
                r.FontFamily = CurrentFontFamily;
                r.Foreground = CurrentForeground;
                this.CaretPosition = r.ElementEnd;
                fontchanged = false;
            }
            else
                base.OnTextInput(e);
        }
    

    如果您的 CurrentFontProperty 已更改,请获取插入符号位置并使用新的文本输入创建一个新的运行并设置 FontFamily = CurrentFontFamily。如果carret超过一个单词,您也可以更改整个单词,这篇文章可能会发现Navigate Words in RichTextBox这个词。

    【讨论】:

      【解决方案2】:

      这是我用来避免覆盖富文本框的方法。这允许您更改选择的样式(如果有),或者更改插入符号后“要添加”文本的样式。希望对您有所帮助。

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

      【讨论】:

        【解决方案3】:

        你会在 RichTextBox 中使用 RUN,类似于:

        <RichTextBox>
           <Run FontFamily="Arial">My Arial Content</Run>
           <Run FontFamily="Times" FontWeight="Bold">My bolded Times content</Run>
           <Run>My Content that inherits Font From the RTB</Run>
        </RichTextBox>
        

        好的,这可以与一些低级的 doo hickies 一起玩。但是我们开始了:

        首先,将几个 ToggleButtons 和一个 RichTextBox 添加到 XAML 表单。在富文本框中,您将为其提供一些命令绑定,以便让系统知道一切都可以协同工作。

        这是 XAML:

        <RichTextBox Height="119" Name="RichTextBox1" Width="254" >
               <RichTextBox.CommandBindings>
                    <CommandBinding Command="EditingCommands.ToggleBold" CanExecute="CommandBinding_CanExecute"   ></CommandBinding>
                    <CommandBinding Command="EditingCommands.ToggleItalic" CanExecute="CommandBinding_CanExecute"   ></CommandBinding>
               </RichTextBox.CommandBindings>
        </RichTextBox>
        <ToggleButton MinWidth="40" Command="EditingCommands.ToggleBold"  Height="23" HorizontalAlignment="Left" Name="Button1" VerticalAlignment="Top" Width="75" CommandTarget="{Binding ElementName=RichTextBox1}" >Bold</ToggleButton>
        <ToggleButton MinWidth="40" Command="EditingCommands.ToggleBold"  Height="23" HorizontalAlignment="Left"  Name="Button2" VerticalAlignment="Top" Width="75" CommandTarget="{Binding ElementName=RichTextBox1}" >Italics</ToggleButton>
        

        现在,有一个 RichTextbox 和两个切换按钮,这些切换按钮分别与 ToggleBold/ToggleItalics 的命令绑定相关。

        在CODE方面,我有这两种方法:

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)      
        End Sub
        
        Private Sub CommandBinding_CanExecute(ByVal sender As System.Object, ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
             e.CanExecute = True
        End Sub
        

        BUTTON CLICK 事件处理程序之所以存在,是因为按钮需要事件处理程序才能使用。

        CanExecute 告诉按钮该值是否可用于加粗(例如,您可以检查长度,如果 RTB 为空,则不要尝试加粗)。

        现在,为了对事物进行真正的低级控制,您将不得不在 RichTextFormat 中进行操作。关注link 了解更多信息。

        【讨论】:

        • 我想动态地改变它,就像命令一样。这对于静态文本很好。但是在 RichTextBox 中的定位是通过键盘输入动态地产生具有不同 Text 属性的文本。
        • 然后查看 RTF,并读/写它。 devcity.net/PrintArticle.aspx?ArticleID=356
        • 问题是第一个 和以下所有内容将从它们的容器(可能是 RichTextEditor 后面的 FlowDocument)继承 textElement 属性,因此在更改编辑器的字体时它会改变引用它的所有元素的字体。到目前为止,我可以通过在更改字体时生成新的运行标签来订阅 PreviewKey 来管理它,但是我必须过滤键盘输入。我确信有更好的方法来做到这一点,所有的 EditingCommnads 都使用粗体、斜体、fontSize 做同样的事情,当然还有一种花哨的方式。
        • 没有更改字体系列或颜色的命令。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-18
        • 2011-05-05
        相关资源
        最近更新 更多