簡體   English   中英

WPF - 如果我在更改大小后單擊 RichTextBox,RichTextBox 字體大小不會改變

[英]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)
    {

    }
}

我怎樣才能使這項工作?

您可以在下面的短代碼中嘗試一些解決方案。

這個想法是將字體系列應用於RichTextBoxTextChanged事件中的鍵入文本。 為了使其工作,有必要確定
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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM