【问题标题】:How to check if text in a RichTextBox is underlined?如何检查 RichTextBox 中的文本是否带下划线?
【发布时间】:2019-08-21 14:34:15
【问题描述】:

我目前正在使用包含工具栏和 RichTextBox 的 WPF 编写文本编辑器。工具栏中的每个按钮定义将应用于所选文本的文本属性(使用 costum 属性)。它工作正常。

问题

如果用户单击文本上的某处,并且将其文本属性应用于当前位置,则应突出显示按钮。当我尝试检查当前选择是否带下划线/删除线时,它不起作用。

代码

private void checkToolBarButtons()
    {
        // this method checks if the button should be highlighted or not.
        Func<Button, object> check = (Button button) =>
        {
            try
            {
                // the button has two costum properties that allow to determine which text property should be
                // applied to the selected text.
                string propString = ToolBarButton.GetDocumentProperty(button);
                // e.g. "TextDecorations"
                DependencyProperty dependency = this.getPropertyByString(propString);
                // e.g. TextDecorationsProperty
                string propertyValue = ToolBarButton.GetDocumentPropertyValue(button);
                // e.g. "Underline"

                if (dependency != null)
                {
                    TextRange selectionRange = new TextRange(this.richTextBox.Selection.Start, this.richTextBox.Selection.End);
                    object selectedProperty = selectionRange.GetPropertyValue(dependency);

                    if (selectedProperty.GetType() == typeof(TextDecorationCollection) && ((TextDecorationCollection)selectedProperty).Count > 0)
                    {
                        if (selectedProperty.Equals(TextDecorations.Underline))
                        {
                            // this code is never reached 
                            selectedProperty = "Underline";
                        }
                        else if (selectedProperty.Equals(TextDecorations.Strikethrough))
                        {
                            // this code is never reached 
                            selectedProperty = "Strikethrough";
                        }
                    }

                    if (selectedProperty.ToString() == propertyValue)
                    {
                        button.Background = new SolidColorBrush(Colors.Yellow);
                    }
                    else
                    {
                        button.Background = new SolidColorBrush(Colors.LightGray);
                    }
                }
            }
            catch (Exception ex)
            {

            }
            return null;
        };

        foreach (FrameworkElement ctrl in toolBar.Children)
        {
            if (ctrl.GetType() == typeof(StackPanel))
            {
                foreach (Button button in ((Panel)ctrl).Children)
                {
                    check(button);
                }
            }
            else if (ctrl.GetType() == typeof(Button))
            {
                check((Button)ctrl);
            }
        }
    }

    /// <summary>
    /// converts a string to a DependencyProperty
    /// </summary>
    /// <param name="propertyString"></param>
    /// <returns></returns>
    private DependencyProperty getPropertyByString(string propertyString)
    {
        switch (propertyString)
        {
            case ("FontStyleProperty"): return FontStyleProperty;
            case ("FontWeightProperty"): return FontWeightProperty;
            case ("TextDecorations"): return TextBlock.TextDecorationsProperty;
            case ("TextAlignment"): return TextBlock.TextAlignmentProperty;
            default:
                break;
        }

        return null;
    }

XAML

<UserControl x:Class="EasyControls.TextEditor"
         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:EasyControls"
         mc:Ignorable="d" Height="236.318" Width="493.571">
<Border BorderThickness="1" BorderBrush="Blue">
    <DockPanel Background="White">
        <WrapPanel x:Name="toolBar" Orientation="Horizontal" Background="#FF2B2B8F" DockPanel.Dock="Top">
            <StackPanel x:Name="textAlignPanel"  Background="#FFF4F4F5" Height="21" Orientation="Horizontal" Margin="2">
                <Button local:ToolBarButton.DocumentProperty="TextAlignment" local:ToolBarButton.DocumentPropertyValue="Left"
                         Margin="2 2 2 2" Click="ToolBarButton_Click" Width="20">
                    <Image Source="img/Left.png" />
                </Button>
                <Button local:ToolBarButton.DocumentProperty="TextAlignment" local:ToolBarButton.DocumentPropertyValue="Center"
                         Margin="2 2 2 2" Click="ToolBarButton_Click" Width="20">
                    <Image Source="img/Center.png" />
                </Button>
                <Button local:ToolBarButton.DocumentProperty="TextAlignment" local:ToolBarButton.DocumentPropertyValue="Right"
                         Margin="2 2 2 2" Click="ToolBarButton_Click" Width="20">
                    <Image Source="img/Right.png" />
                </Button>
                <Button local:ToolBarButton.DocumentProperty="TextAlignment" local:ToolBarButton.DocumentPropertyValue="Justify"
                         Margin="2 2 2 2" Click="ToolBarButton_Click" Width="20">
                    <Image Source="img/Justify.png" />
                </Button>
            </StackPanel>
            <StackPanel x:Name="fontStylePanel"  Background="#FFF4F4F5" Height="21" Orientation="Horizontal">
                <Button local:ToolBarButton.DocumentProperty="FontWeightProperty" local:ToolBarButton.DocumentPropertyValue="Bold"
                         Margin="2 2 2 2" Click="ToolBarButton_Click" FontWeight="Bold" Width="20">
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">b</TextBlock>
                </Button>
                <Button local:ToolBarButton.DocumentProperty="FontStyleProperty" local:ToolBarButton.DocumentPropertyValue="Italic"
                         Margin="1 2 2 2" Click="ToolBarButton_Click" FontStyle="Italic" Width="20">
                    <TextBlock  HorizontalAlignment="Center" VerticalAlignment="Center">i</TextBlock>
                </Button>
                <Button local:ToolBarButton.DocumentProperty="TextDecorations" local:ToolBarButton.DocumentPropertyValue="Underline"
                        Margin="1 2 2 2" Click="ToolBarButton_Click" Width="20" >
                    <TextBlock TextDecorations="Underline"  HorizontalAlignment="Center" VerticalAlignment="Center">u</TextBlock>
                </Button>
                <Button local:ToolBarButton.DocumentProperty="TextDecorations" local:ToolBarButton.DocumentPropertyValue="Strikethrough"
                        Margin="1 2 2 2" Click="ToolBarButton_Click" Width="20" >
                    <TextBlock TextDecorations="Strikethrough" HorizontalAlignment="Center" VerticalAlignment="Center">s</TextBlock>
                </Button>
            </StackPanel>
        </WrapPanel>
        <RichTextBox x:Name="richTextBox" Background="White" SelectionChanged="RichTextBox_SelectionChanged" IsDocumentEnabled="True" DockPanel.Dock="Bottom" VerticalAlignment="Stretch" BorderThickness="0" BorderBrush="{x:Null}">
            <FlowDocument>
                <Paragraph/>
            </FlowDocument>
        </RichTextBox>
    </DockPanel>
</Border>

【问题讨论】:

  • 也许你应该试试this
  • @geronimo678 是的,我在重建您未显示的 XAML 时出错。我在下划线按钮上有local:ToolBarButton.DocumentProperty="FontStyleProperty",而不是local:ToolBarButton.DocumentProperty="TextDecorations"。一旦我解决了这个问题,只要我在富文本框中的选择发生变化时调用checkToolBarButtons(),你的代码就可以像你写的那样为我工作。
  • @geronimo678 感谢您添加 XAML。你知道,那些附加的属性可能是枚举。让我感兴趣的是,如果集合包含 xTextDecorationCollection.Equals(x) 返回 true。
  • @EdPlunkett 你完全正确,我应该使用枚举。 Equals() 方法对我不起作用(请参阅我对帖子答案的第一条评论)。
  • @geronimo678 好的,我明白了:TextDecorations.Underline 是 TextDecorationCollection 的一个实例,其中包含一个 TextDecorationLocation,UnderlineTextDecorations.Strikethrough 也是一个包含一个项目的集合。当所选文本带有下划线且未被删除时,selectedProperty 实际上是同一个对象实例,因此 Equals() 返回 true 并且您的代码有效(对我而言)。如果文本带有下划线和删除线,则您的检查都不正确,因为selectedProperty 是一个不同的集合,其中包含两个项目。

标签: c# wpf


【解决方案1】:

您首先检查selectedProperty 是否是TextDecorationCollection,然后在您期望它是TextDecorations.UnderlineTextDecorations.Strikethrough 之后立即检查?这是没有意义的。

您可能希望将selectedProperty 转换为TextDecorationCollection,然后对其进行迭代。像这样的:

...
TextRange selectionRange = new TextRange(this.richTextBox.Selection.Start, this.richTextBox.Selection.End);
object selectedProperty = selectionRange.GetPropertyValue(TextBlock.TextDecorationsProperty);

TextDecorationCollection textDecorationCollection = selectedProperty as TextDecorationCollection;
if (textDecorationCollection != null)
{
    foreach (TextDecoration textDecoration in textDecorationCollection)
    {
        if (textDecoration.Location == TextDecorationLocation.Underline)
        {
            // this code is never reached 
            selectedProperty = "Underline";
        }
        else if (textDecoration.Location == TextDecorationLocation.Strikethrough)
        {
            // this code is never reached 
            selectedProperty = "Strikethrough";
        }
    }
}

【讨论】:

  • 非常感谢。遍历集合是这里的重点。但是“textDecoration.Equals(TextDecorations.Underline)”不起作用,因为它不是同一类型。您需要使用“textDecoration.Location == TextDecorationLocation.Underline”等等。
  • 我的错,我在重建他的 XAML 时出错了。如果 DocumentProperty 是“TextDecorations”并且 DocumentPropertyValue 是“Underline”,那么如果在 RichTextBox_SelectionChanged 上调用,他的代码实际上会像编写的那样工作
  • @EdPlunkett 对不起,也许我也应该添加 XAML 代码...
  • @geronimo678 那和附加的属性会很有帮助。
  • @EdPlunkett 我添加了 XAML 代码,也许它可以帮助其他人。下次我会从头补充。
猜你喜欢
  • 2014-03-22
  • 2014-10-14
  • 2011-02-02
  • 2018-09-19
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
  • 2010-09-16
  • 2020-08-21
相关资源
最近更新 更多