Как установить Шрифт 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 могу ограничить изменение, которое будет применено только к выбранной области. Но как для следующего - еще напечатанный текст?

12
задан Néstor Sánchez A. 6 December 2009 в 08:01
поделиться

3 ответа

Чтобы установить FontFamily на основе позиции курсора, вам необходимо определить настраиваемый элемент управления со свойством зависимости, которое помогает вставить новый раздел Run путем переопределения метода 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: Если вы не используете модели представления, дайте мне знать, и я тоже добавлю код базового класса; в противном случае вам также может помочь google / 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:

using System.Windows;

namespace RichTextboxFont.Views
{
  public partial class MainView : Window
  {
    public MainView()
    {
      InitializeComponent();
      this.DataContext = new ViewModels.MainViewModel();
    }
  }
}
8
ответ дан 2 December 2019 в 22:22
поделиться

Это не совсем тривиальный ответ.

Чтобы сделать встроенное форматирование текста в Rich TextBox, как вы хотите, вам придется изменить свойство Document в RichTextBox. Очень просто, что-то вроде этого будет работать

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

Я думаю, вы можете создать пользовательский элемент управления, который создает новый блочный элемент и устанавливает нужные вам свойства шрифта на основе пользовательского ввода.

Например, если пользователь набирает что-то, а затем нажимает кнопку bold. Вы хотите обернуть предыдущий текст в пробел и создать новый элемент пробела, установив FontWeight на bold, тогда последующий текст будет обернут в полужирный пробел.

Опять же, это не тривиальное решение, но я не могу придумать другого способа достичь того, что вам нужно.

0
ответ дан 2 December 2019 в 22:22
поделиться

Есть гораздо более простой способ сделать это: реализовать панель инструментов для вашего RichTextBox.

В отличие от WinForms, RichTextBox в WPF по умолчанию не имеет панели инструментов, но ее очень легко создать самостоятельно. RichTextBox автоматически обрабатывает многие EditingCommands, поэтому нужно просто создать панель инструментов и несколько кнопок. Microsoft предоставила пример кода для этого в нижней части обзора RichTextBox на MSDN.

К сожалению, эти команды редактирования не включают установку свойства FontFace для выделения, хотя вы можете создать поле со списком на панели инструментов, которое может инициировать изменение с помощью обработчика событий в файле кода программной части.

Этот подход используется Грегором Проссом в этой статье 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. Если пользователю приходится вручную нажимать вкладку или щелкать RichTextBox, создается новое выделение текста, и вы теряете выбранные параметры форматирования.

Один из ответов на этот вопрос StackOverflow обсуждает эту проблему. WPF Richtextbox FontFace/FontSize

2
ответ дан 2 December 2019 в 22:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: