Wpf 如何为下一个要写入的文本设置RichTextBox字体?

Wpf 如何为下一个要写入的文本设置RichTextBox字体?,wpf,xaml,fonts,richtextbox,Wpf,Xaml,Fonts,Richtextbox,我需要为要写入RichTextBox的下一个文本设置字体系列。 我试着用 <RichTextBox x:Name="RichTextEditor" MaxWidth="1000" SpellCheck.IsEnabled="True" FontFamily="{Binding ElementName=TextFontComboBox, Path=SelectedItem}" FontSize="{Binding ElementName=T

我需要为要写入RichTextBox的下一个文本设置字体系列。 我试着用

<RichTextBox x:Name="RichTextEditor" MaxWidth="1000" SpellCheck.IsEnabled="True"
             FontFamily="{Binding ElementName=TextFontComboBox, Path=SelectedItem}"
             FontSize="{Binding ElementName=TextSizeComboBox, Path=SelectedValue}"
             Width="Auto" Height="Auto" HorizontalScrollBarVisibility="Auto" 
VerticalScrollBarVisibility="Auto" />


…但它改变了整个文本。我假设使用Selection属性,我可以将更改限制为仅应用于选定区域。但是下一个尚未键入的文本如何处理呢?

这并不是一个简单的答案

要在RichTextBox中执行您想要的内联文本格式设置,必须修改RichTextBox的Document属性。很简单,像这样的东西会起作用

<RichTextBox >
  <RichTextBox.Document>
    <FlowDocument>
      <Paragraph>
        <Run>Something</Run>
        <Run FontWeight="Bold">Something Else</Run>
      </Paragraph>
    </FlowDocument>
  </RichTextBox.Document>
</RichTextBox>  

某物
别的
我认为您可以创建一个自定义控件来创建一个新的块元素,并根据用户输入设置所需的字体属性

例如,如果用户键入内容,则按粗体。您可能希望在运行中包装上一个文本,并创建一个新的运行元素,将FontWeight设置为粗体,然后在粗体运行中包装下一个文本


同样,这不是一个简单的解决方案,但我想不出任何其他方法来完成您的目标。

为了根据光标位置设置FontFamily,您需要定义一个自定义控件,该控件具有依赖属性,通过覆盖ontextput方法来帮助插入新的运行节

我包含了大部分代码,您需要修改名称空间以适应您的开发环境

代码使用ViewModel来管理可用字体,并管理字体是否更改。 此代码只是一个原型,不处理两个控件之间的焦点问题

要使用此代码:
1-在Richtect框中键入一些文本。
2-更改组合框中的字体。
3-选项卡返回RichTextBox。
4-再键入一些文本

以下是自定义RichTextBox控件:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;

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

    public FontFamily CurrentFontFamily
    {
       get
       {
         return (FontFamily)GetValue(CurrentFontFamilyProperty);
       }
       set
       {
         SetValue(CurrentFontFamilyProperty, value);
       }
    }

    private static void OnCurrentFontChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {}

    protected override void OnTextInput(TextCompositionEventArgs e)
    {
      ViewModels.MainViewModel mwvm = this.DataContext as ViewModels.MainViewModel;
      if ((mwvm != null) && (mwvm.FontChanged))
      {
        TextPointer textPointer = this.CaretPosition.GetInsertionPosition(LogicalDirection.Forward);
        Run run = new Run(e.Text, textPointer);
        run.FontFamily = this.CurrentFontFamily;
        this.CaretPosition = run.ElementEnd;
        mwvm.FontChanged = false;
      }
      else
      {
         base.OnTextInput(e);
      }
    }
  } 
}
以下是XAML:

<Window x:Class="RichTextboxFont.Views.MainView"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:RichTextboxFont.Views" 
  xmlns:ViewModels="clr-namespace:RichTextboxFont.ViewModels" 
  Title="Main Window" 
  Height="400" Width="800">
  <DockPanel>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <ComboBox ItemsSource="{Binding Path=Fonts}" 
                  SelectedItem="{Binding Path=SelectedFont, Mode=TwoWay}"/>
        <local:RichTextBoxCustom Grid.Row="1" 
                                 CurrentFontFamily="{Binding Path=SelectedFont, Mode=TwoWay}" 
                                 FontSize="30"/>
    </Grid>
  </DockPanel>
</Window>

有一种更简单的方法:为RichTextBox实现一个工具栏

与WinForms不同,WPF中的RichTextBox默认情况下没有工具栏,但自己创建一个工具栏非常容易。RichTextBox会自动处理许多问题,因此只需创建一个工具栏和一些按钮。微软已经在文章的底部提供了这方面的示例代码

不幸的是,这些编辑命令不包括设置选择的FontFace属性,尽管您可以在工具栏上创建一个组合框,通过codebehind文件中的事件处理程序触发更改

这就是Gregor Pross在这篇CodePlex文章中采用的方法:

该项目是用德语评论的,但源代码本身写得非常清楚。用于字体选择器组合框的codebehind如下所示:

    private void Fonttype_DropDownClosed(object sender, EventArgs e)
    {            
        string fontName = (string)Fonttype.SelectedItem;

        if (fontName != null)
        {                
            RichTextControl.Selection.ApplyPropertyValue(System.Windows.Controls.RichTextBox.FontFamilyProperty, fontName);
            RichTextControl.Focus();
        }
    }
人们难以选择字体的主要原因是,在选择字体后,必须将焦点返回到RichTextBox。如果用户必须手动按tab键或在RichTextBox中单击,则会创建一个新的文本选择,您将丢失所选的格式选项

这个问题的一个答案讨论了这个问题。

您是否试图提供如下效果:当用户按粗体键时,然后键入文本,键入的文本应变为粗体,直到删除粗体效果?完全正确!与标准文本处理器中的相同。这是如此基本和明显,令人遗憾的是WPF默认没有它!我认为使用MVVM方法太复杂了。您可以使用代码隐藏中的事件处理程序在几行代码中解决这个问题。谢谢这是最简单的部分。存在要应用字体或其他格式属性的选定文本时。复杂的部分是没有选择的时候。你帮我省了很多麻烦。非常感谢!
using System.Windows;

namespace RichTextboxFont.Views
{
  public partial class MainView : Window
  {
    public MainView()
    {
      InitializeComponent();
      this.DataContext = new ViewModels.MainViewModel();
    }
  }
}
    private void Fonttype_DropDownClosed(object sender, EventArgs e)
    {            
        string fontName = (string)Fonttype.SelectedItem;

        if (fontName != null)
        {                
            RichTextControl.Selection.ApplyPropertyValue(System.Windows.Controls.RichTextBox.FontFamilyProperty, fontName);
            RichTextControl.Focus();
        }
    }