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

时间:2009-12-06 08:01:30

标签: wpf xaml fonts richtextbox

我需要为要在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属性,我可以将更改限制为仅应用于所选区域。但是如何为下一个尚未输入的文本?

3 个答案:

答案 0 :(得分:8)

为了根据光标位置设置FontFamily,您需要定义一个带有依赖项属性的自定义控件,该属性可以通过覆盖OnTextInput方法来帮助插入新的“运行”部分。

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

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

使用此代码:
1-在RichTectBox中键入一些文本 2-更改ComboBox中的字体 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>

这是ViewModel: 如果你不使用视图模型,请告诉我,我也会添加基类代码;否则,谷歌/ stackoverflow也可以帮助你。

using System.Collections.ObjectModel;
using System.Windows.Media;

namespace RichTextboxFont.ViewModels
{
  public class MainViewModel : ViewModelBase
  {
    #region Constructor

    public MainViewModel()
    {
       FontFamily f1 = new FontFamily("Georgia");
       _fonts.Add(f1);
       FontFamily f2 = new FontFamily("Tahoma");
       _fonts.Add(f2);
    }

    private ObservableCollection<FontFamily> _fonts = new ObservableCollection<FontFamily>();
    public ObservableCollection<FontFamily> Fonts
    {
      get
      {
         return _fonts;
      }
      set
      {
        _fonts = value;
        OnPropertyChanged("Fonts");
      }
    }

    private FontFamily _selectedFont = new FontFamily("Tahoma");
    public FontFamily SelectedFont
    {
      get
      {
        return _selectedFont;
      }
      set
      {
        _selectedFont = value;
        FontChanged = true;
        OnPropertyChanged("SelectedFont");
      }
    }

    private bool _fontChanged = false;
    public bool FontChanged
    {
      get
      {
         return _fontChanged;
      }
      set
      {
        _fontChanged = value;
        OnPropertyChanged("FontChanged");
      }
    }

  #endregion
  }
}

这是我初始化ViewModel的Window代码隐藏:

using System.Windows;

namespace RichTextboxFont.Views
{
  public partial class MainView : Window
  {
    public MainView()
    {
      InitializeComponent();
      this.DataContext = new ViewModels.MainViewModel();
    }
  }
}

答案 1 :(得分:2)

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

与WinForms不同,WPF中的RichTextBox默认没有工具栏,但是自己创建一个很容易。 RichTextBox自动处理许多EditingCommands,因此只需创建工具栏和一些按钮即可。 Microsoft已在RichTextBox Overview on MSDN

的底部为此提供了示例代码

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

这是Gregor Pross撰写的CodePlex文章中采用的方法:WPF RichTextEditor

该项目用德语评论,但源本身写得很清楚。用于他的字体选择器ComboBox的代码隐藏如下所示:

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

人们在使用FontFace选项时遇到的主要原因是在完成字体选择后,必须将焦点返回到RichTextBox 。如果用户必须手动按Tab键或单击RichTextBox,则会创建新的文本选择,并且您将丢失所选的格式选项。

此StackOverflow问题的答案之一讨论了该问题。 WPF Richtextbox FontFace/FontSize

答案 2 :(得分:0)

这不是一个简单的答案。

要在Rich TextBox中进行内联文本格式化,您需要修改RichTextBox的Document属性。很简单,像这样的东西会起作用

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

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

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

同样,这不是一个简单的解决方案,但我想不出任何其他方式来实现你的目标。