简体   繁体   English

通过组合框更改RichTextBox选择的字体大小无法正常工作

[英]Changing the font size of a RichTextBox Selection through a ComboBox doesn't work properly

I have created a very simple WPF Window consisting of a Grid containing one RichTextBox and one ComboBox . 我创建了一个非常简单的WPF窗口,该窗口由一个包含一个RichTextBox和一个ComboBox的网格组成。 I use the ComboBox for changing and looking up the font size of the RichTextBox selection. 我使用ComboBox更改和查找RichTextBox选择的字体大小。

Here's the code-behind file of my XAML: 这是我的XAML的代码隐藏文件:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        // Add the font sizes.
        for (var i = 1; i < 72; i++)
        {
            FontSize.Items.Add((double) i);
        }
    }

    private void MyTextBox_SelectionChanged(object sender, RoutedEventArgs e)
    {
        // If the selection changes, update the font size in the ComboBox.
        FontSize.SelectedValue = (double) MyTextBox.Selection.GetPropertyValue(TextBlock.FontSizeProperty);
    }

    private void FontSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        // If the selected size changes, change the size of the selection in the RichTextBox.
        if (FontSize.SelectedItem != null)
            MyTextBox.Selection.ApplyPropertyValue(TextBlock.FontSizeProperty, FontSize.SelectedItem);
    }
}

There are two things here: 这里有两件事:

  1. MyTextBox_SelectionChanged updates the ComboBox with the font size of the selection. MyTextBox_SelectionChanged用选择的字体大小更新ComboBox
  2. FontSize_SelectionChanged changes the font size of the selection. FontSize_SelectionChanged更改所选内容的字体大小。

You can see the problem below: 您可以看到以下问题:

在此处输入图片说明

When I make a selection and change the font size, it changes perfectly. 当我进行选择并更改字体大小时,它会完美变化。 But the moment I click on another text with a different font size it changes back again. 但是,当我单击另一种具有不同字体大小的文本时,它会再次变回原来的状态。

What is causing this behavior? 是什么导致此行为?

Edit: Here's the XAML file: 编辑:这是XAML文件:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ComboBox x:Name="FontSize" HorizontalAlignment="Left" VerticalAlignment="Top" Width="497" Margin="10,10,0,0" SelectionChanged="FontSize_SelectionChanged"/>
        <RichTextBox x:Name="MyTextBox" HorizontalAlignment="Left" Height="273" VerticalAlignment="Top" Width="497" Margin="10,37,0,0" RenderTransformOrigin="0.358,0.48" SelectionChanged="MyTextBox_SelectionChanged">
            <FlowDocument>
                <Paragraph>
                    <Run Text="RichTextBox"/>
                </Paragraph>
            </FlowDocument>
        </RichTextBox>

    </Grid>
</Window>

Edit 2: Here's the short explanation of what I did when I was debugging it: 编辑2:这是我调试时所做的简短说明:

  1. There are two debug points, one at MyTextBox_SelectionChanged , and one at FontSize_SelectionChanged . 有两个调试点,一个在MyTextBox_SelectionChanged ,另一个在FontSize_SelectionChanged
  2. When I change the font size, I click on F5 and continue. 当我更改字体大小时,我单击F5并继续。
  3. When I click on another part of the text (that has the default size), MyTextBox_SelectionChanged is called. 当我单击文本的另一部分(具有默认大小)时,将调用MyTextBox_SelectionChanged The Selection.Text is empty. Selection.Text为空。
  4. Then I continue again and stop at the call to FontSize_SelectionChanged . 然后,我再次继续并停止调用FontSize_SelectionChanged But still the Selection.Text is empty, but my older selection "Rich" returns back to the old font size. 但是Selection.Text仍然为空,但是我的旧选择“ Rich”返回到旧字体大小。

Edit 3: This problem is mentioned in Sams Teach Yourself WPF in 24 Hours first printing July 2008, page 135, " Making the Text Editor Work as Expected ", item 9. I didn't understand the explanation there and created a short sample illustrating that specific problem. 编辑3:此问题在2008年7月第一次印刷的《 萨姆斯自学WPF》(第24页)第135页“ 使文本编辑器按预期工作 ”中的项目9中提到。我不理解那里的解释,并创建了一个简短的示例来说明那个具体的问题。

What seems to be happening is that when you click to clear the selection, this causes your TextBox.SelectionChanged event handler ( MyTextBox_SelectionChanged ) to be invoked while the Selection represents an empty selection (ie, just an insertion point). 似乎正在发生的事情是,当您单击以清除选择时,这会导致您的TextBox.SelectionChanged事件处理程序( MyTextBox_SelectionChanged )被调用,而Selection代表一个空选择(即,只是一个插入点)。 Your handler sets the combo box's SelectedValue , using the empty selection's font size, which is a perfectly reasonable thing to do even if the selection is empty. 您的处理程序使用空选择的字体大小设置组合框的SelectedValue ,即使选择为空,这也是完全合理的做法。 (The insertion point still has a font size.) (插入点仍具有字体大小。)

Changing the SelectedValue of course causes your ComboBox.Selection event handler ( FontSize_SelectionChanged ) to run. 更改SelectedValue当然会导致您的ComboBox.Selection事件处理程序( FontSize_SelectionChanged )运行。 And because that event handler has no easy way to distinguish between an event caused by the user selecting a new value, and the event being caused by your code changing the SelectedValue property, it goes ahead and attempts to modify the selection's font size, which you probably don't want to be doing in this particular case. 并且由于该事件处理程序没有简便的方法来区分由用户选择新值引起的事件和由代码更改SelectedValue属性引起的事件,因此它将继续尝试更改选择的字体大小,可能不想在这种特殊情况下这样做。

Even so, you'd think it'd be OK, because the selection is empty, and you're just attempting to set its font size to be whatever its font size already is. 即使这样,您仍会认为还可以,因为选择为空,而您只是试图将其字体大小设置为已经存在的字体大小。 But here's the weird thing: when you call ApplyPropertyValue on this empty selection, it appears to set the FontSize for the entire document. 但这是奇怪的事情:当您对此空选择调用ApplyPropertyValue时,它似乎为整个文档设置了FontSize

So the effect is that when you click to clear the selection, your code sets the entire document's font size to be whatever the font size is at the point where you click. 因此,效果是,当您单击以清除选择时,您的代码将整个文档的字体大小设置为您单击时的字体大小。

I suspect that's a bug in ApplyPropertyValue , because it only happens if the text you select initially was selected by dragging from left to right, starting at the very first character. 我怀疑这是ApplyPropertyValue的错误,因为只有当您最初选择的文本是从第一个字符开始从左向右拖动来选择时,才会发生。 Then again, it's not entirely clear what the behaviour is meant to be if you apply formatting to an empty selection. 再说一遍,如果将格式化应用于空选择,则行为的含义还不完全清楚。 So perhaps this is more just a case of invoking undefined behaviour rather than hitting a definite bug in WPF. 因此,也许这仅仅是调用未定义行为的情况,而不是在WPF中遇到确定的错误。

In any case, a reasonable way to fix this is by modifying your combo box change handler: 无论如何,解决此问题的合理方法是修改组合框更改处理程序:

if (FontSize.SelectedItem != null && !MyTextBox.Selection.IsEmpty)
{
    MyTextBox.Selection.ApplyPropertyValue(
        TextBlock.FontSizeProperty, FontSize.SelectedItem);
}

This only attempts to change the selection's font size if the selection is non-empty. 如果选择为非空,则仅尝试更改选择的字体大小。

When you select your Text, then change the size over the Menu, your code is still selected even though you don't see the selection anymore, now when you select your code the SelectionChanged method fires before the MyTextBoxSelection changes, ( i just guess/believe that, i think i had such a problem once). 当您选择文本,然后在菜单上更改大小时,即使您再也看不到选择内容,您的代码仍会被选中,现在,当您选择代码时,在MyTextBoxSelection更改之前,SelectionChanged方法将触发((我只是猜想/相信我曾经有过这样的问题)。 Now you change your Fontsize and the Fontsize method fires which accesses the not updated Selection, making your last change void. 现在,您更改了Fontsize,并触发了Fontsize方法,该方法将访问未更新的Selection,从而使上一次更改无效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM