wpf 通过 ComboBox 更改 RichTextBox 选择的字体大小无法正常工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15712150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:23:15  来源:igfitidea点击:

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

c#wpfxamlevents

提问by hattenn

I have created a very simple WPF Window consisting of a Grid containing one RichTextBoxand one ComboBox. I use the ComboBoxfor changing and looking up the font size of the RichTextBoxselection.

我创建了一个非常简单的 WPF 窗口,它由一个包含 1RichTextBox和 1的 Grid 组成ComboBox。我使用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_SelectionChangedupdates the ComboBoxwith the font size of the selection.
  2. FontSize_SelectionChangedchanges the font size of the selection.
  1. MyTextBox_SelectionChangedComboBox使用选择的字体大小更新。
  2. FontSize_SelectionChanged更改选择的字体大小。

You can see the problem below:

你可以看到下面的问题:

enter image description here

在此处输入图片说明

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

Edit 3:This problem is mentioned in Sams Teach Yourself WPF in 24 Hoursfirst 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:这个问题在Sams Teach Yourself WPF in 24 Hours首次印刷 2008 年 7 月,第 135 页,“使文本编辑器按预期工作”,第 9 项中提到。我不明白那里的解释,并创建了一个简短的示例说明那个特定的问题。

采纳答案by Ian Griffiths

What seems to be happening is that when you click to clear the selection, this causes your TextBox.SelectionChangedevent handler (MyTextBox_SelectionChanged) to be invoked while the Selectionrepresents an empty selection (i.e., just an insertion point). 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. (The insertion point still has a font size.)

似乎正在发生的事情是,当您单击以清除选择时,这会导致您的TextBox.SelectionChanged事件处理程序 ( MyTextBox_SelectionChanged) 被调用,而Selection表示空选择(即,只是一个插入点)。您的处理程序SelectedValue使用空选择的字体大小设置组合框的,即使选择为空,这也是完全合理的做法。(插入点仍然具有字体大小。)

Changing the SelectedValueof course causes your ComboBox.Selectionevent handler (FontSize_SelectionChanged) to run. 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 SelectedValueproperty, 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当然会导致您的ComboBox.Selection事件处理程序 ( FontSize_SelectionChanged) 运行。并且因为该事件处理程序没有简单的方法来区分由用户选择新值引起的事件和由您的代码更改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 ApplyPropertyValueon this empty selection, it appears to set the FontSizefor 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. 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.

我怀疑这是ApplyPropertyValue. 再说一次,如果您将格式应用于空选择,则不完全清楚行为的含义。所以也许这更像是调用未定义行为的情况,而不是在 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.

如果选择非空,这只会尝试更改选择的字体大小。

回答by Master117

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). Now you change your Fontsize and the Fontsize method fires which accesses the not updated Selection, making your last change void.

当您选择文本,然后更改菜单上的大小时,即使您不再看到选择,您的代码仍然被选中,现在当您选择代码时,SelectionChanged 方法会在 MyTextBoxSelection 更改之前触发,(我只是猜测/相信,我想我曾经遇到过这样的问题)。现在您更改您的 Fontsize 并且 Fontsize 方法会触发访问未更新的选择,从而使您的最后一次更改无效。