[英]WPF - RichTextBox font size won't change if I click in RichTextBox after changing size
我正在使用 WPF 應用程序(.NET Framework)並嘗試制作一個與寫字板類似的字體名稱和字體大小的 UserControl。 我正在使用RichTextBox
來制作它。 我現在正在測試字體大小。 它有時有效,但並非總是如此。
如果我更改字體大小並在不單擊 RichTextBox 的情況下開始輸入,那么它可以工作。
如果我更改字體大小,然后在 RichTextBox 中單擊,然后開始輸入,字體大小與以前相同。 它沒有使用 28 碼。
字處理器.xaml
<UserControl x:Class="TabControlWithRichTextBox.Views.Controls.WordProcessor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TabControlWithRichTextBox.Views.Controls"
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<DockPanel>
<ToolBar DockPanel.Dock="Top">
<ComboBox Name="comboBoxFontFamily" Width="150" IsEditable="False" ItemsSource="{Binding Path=SystemFontFamilyNames, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
<ComboBox Name="comboBoxFontSize" Width="50" IsEditable="False" ItemsSource="{Binding Path=FontSizes, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" SelectedIndex="{Binding SelectedIndexFontSize, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" SelectionChanged="comboBoxFontSize_SelectionChanged" />
</ToolBar>
<RichTextBox Name="richTextBoxEditor" FontFamily="{Binding CurrentFontFamily, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" FontSize="{Binding CurrentFontSize, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" TextOptions.TextFormattingMode="Ideal" TextOptions.TextRenderingMode="Aliased" AcceptsTab="True" AcceptsReturn="True" SelectionChanged="richTextBoxEditor_SelectionChanged" VerticalScrollBarVisibility="Auto" Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}, Path=ActualWidth}" TextChanged="richTextBoxEditor_TextChanged" />
</DockPanel>
</UserControl>
字處理器.xaml.cs
public partial class WordProcessor : UserControl, INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public System.Collections.ObjectModel.ObservableCollection<double> FontSizes { get; set; } = new System.Collections.ObjectModel.ObservableCollection<double>() { 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 };
public System.Collections.ObjectModel.ObservableCollection<string> SystemFontFamilyNames { get; set; } = new System.Collections.ObjectModel.ObservableCollection<string>() { "Arial", "Calibri", "Times New Roman" };
private System.Windows.Media.FontFamily _currentFontFamily = new System.Windows.Media.FontFamily("Arial");
private double _currentFontSize = 12;
private int _selectedIndexFontSize = 0;
public System.Windows.Media.FontFamily CurrentFontFamily
{
get { return _currentFontFamily; }
set
{
if (_currentFontFamily == value)
return;
//set value
_currentFontFamily = value;
OnPropertyChanged(nameof(CurrentFontFamily));
}
}
public double CurrentFontSize
{
get { return _currentFontSize; }
set
{
if (_currentFontSize == value)
return;
//set value
_currentFontSize = value;
OnPropertyChanged(nameof(CurrentFontSize));
}
}
public int SelectedIndexFontSize
{
get { return _selectedIndexFontSize; }
set
{
if (_selectedIndexFontSize == value)
return;
//set value
_selectedIndexFontSize = value;
if (comboBoxFontSize.SelectedItem != null && !String.IsNullOrEmpty(comboBoxFontSize.SelectedItem.ToString()))
CurrentFontSize = Convert.ToDouble(comboBoxFontSize.SelectedItem.ToString());
}
}
public WordProcessor()
{
InitializeComponent();
//initial font
comboBoxFontFamily.SelectedIndex = 0;
//initial font size
comboBoxFontSize.SelectedIndex = 4;
}
protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
private void comboBoxFontFamily_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void comboBoxFontSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (comboBoxFontSize.SelectedItem != null)
{
double fontSize = Convert.ToDouble(comboBoxFontSize.SelectedItem);
var pixelSize = Convert.ToDouble(fontSize) * (96 / 72);
richTextBoxEditor.Selection.ApplyPropertyValue(Inline.FontSizeProperty, pixelSize);
richTextBoxEditor.Focus();
}
}
private void richTextBoxEditor_SelectionChanged(object sender, RoutedEventArgs e)
{
}
private void richTextBoxEditor_TextChanged(object sender, TextChangedEventArgs e)
{
}
}
我怎樣才能使這項工作?
您可以在下面的短代碼中嘗試一些解決方案。
這個想法是將字體系列應用於RichTextBox
的TextChanged
事件中的鍵入文本。 為了使其工作,有必要確定
TextRange
用於輸入的字符,而不是使用TextRange.ApplyPropertyValue()
。
該示例演示了如何應用FontFamily
。 另一個字體參數可能以相同的方式實現。
主窗口.xaml:
<Window x:Class="WpfApp12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="RtbWindow"
Title="MainWindow" Height="350" Width="400">
<Grid>
<DockPanel>
<ToolBar DockPanel.Dock="Top">
<ComboBox SelectedItem="{Binding MyFontFamily, ElementName=RtbWindow}"
ItemsSource="{Binding Source={x:Static Fonts.SystemFontFamilies}}"
MinWidth="150" SelectedIndex="0"/>
</ToolBar>
<RichTextBox Name="rtb" VerticalScrollBarVisibility="Auto" TextChanged="rtb_TextChanged" />
</DockPanel>
</Grid>
</Window>
MainWindow.xaml.cs:
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
namespace WpfApp12
{
public partial class MainWindow : Window
{
public static readonly DependencyProperty MyFontFamilyProperty =
DependencyProperty.Register("MyFontFamily", typeof(FontFamily), typeof(MainWindow), new UIPropertyMetadata(null));
public FontFamily MyFontFamily
{
get => (FontFamily)GetValue(MyFontFamilyProperty);
set => SetValue(MyFontFamilyProperty, value);
}
public MainWindow()
{
InitializeComponent();
}
private void rtb_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
// Preventing a recursive call of the `rtb_TextChanged`.
this.rtb.TextChanged -= new System.Windows.Controls.TextChangedEventHandler(this.rtb_TextChanged);
foreach (var tc in e.Changes)
{
if (tc.AddedLength == 1)
{
TextPointer current = rtb.CaretPosition;
var from = current.GetTextPositionAtOffset(1, LogicalDirection.Backward);
var tr = new TextRange(from, current);
tr.ApplyPropertyValue(TextElement.FontFamilyProperty, MyFontFamily);
}
}
this.rtb.TextChanged += new System.Windows.Controls.TextChangedEventHandler(this.rtb_TextChanged);
}
}
}
GetTextPositionAtOffset()
方法:
using System.Windows.Documents;
namespace WpfApp12
{
public static class TextRangeExt
{
public static TextPointer GetTextPositionAtOffset(this TextPointer position, int offset, LogicalDirection direction = LogicalDirection.Forward)
{
for (TextPointer current = position; current != null; current = position.GetNextContextPosition(direction))
{
position = current;
var context = position.GetPointerContext(direction);
switch (context)
{
case TextPointerContext.Text:
int count = position.GetTextRunLength(direction);
if (offset <= count) { return position.GetPositionAtOffset(direction == LogicalDirection.Backward ? -offset : offset); }
offset -= count;
break;
}
}
return position;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.