如何应用多个 TextDecorations?

How can I apply multiple TextDecorations?

我见过的所有设置下划线、上划线或删除线的示例都是这样的:

// setting underline
textRange.ApplyPropertyValue(Inline.TextDecorationsProperty, 
                             TextDecorations.Underline);

// clearing underline
textRange.ApplyPropertyValue(Inline.TextDecorationsProperty, null );

这对我来说似乎过于简单化; TextDecorationsProperty returns 系列 装饰品 - 您可以将 OverlineUnderlineStrikethrough同时;像这样设置它们会清除整个集合。

这就是我切换它们的方法 TextDecorationLocation:

var textRange = new TextRange(tb.Selection.Start, tb.Selection.End);
var tdp = textRange.GetPropertyValue(Inline.TextDecorationsProperty);
var textDecorations = tdp.Equals(DependencyProperty.UnsetValue)
                      ? new TextDecorationCollection()
                      : tdp as TextDecorationCollection 
                        ?? new TextDecorationCollection();

var strikethroughs = textDecorations.Where(d => d.Location == TextDecorationLocation.Strikethrough)
                                    .ToList();
if (strikethroughs.Any())
{
   foreach (var strike in strikethroughs)
   {
      textDecorations.Remove(strike);
   }
}
else
{
   textDecorations.Add(TextDecorations.Strikethrough);
}

textRange.ApplyPropertyValue(Inline.TextDecorationsProperty, textDecorations);

这是解决这个问题的好方法,还是我让它过于复杂了?

如果您尝试打开和关闭装饰,同时允许它们组合,您可以执行以下操作:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0" Orientation="Horizontal">
        <Button Content="Underline" Click="Underline" />
        <Button Content="Strikethrough"  Click="Strikethrough" />
        <Button Content="Baseline" Click="Baseline" />
        <Button Content="Overline"  Click="Overline" />
    </StackPanel>
    <RichTextBox x:Name="tb" Grid.Row="1" />
</Grid>

然后在代码中

        private void Underline(object sender, RoutedEventArgs e)
    {
        this.SetDecorations(new TextRange(this.tb.Selection.Start, this.tb.Selection.End), TextDecorations.Underline);
    }

    private void Strikethrough(object sender, RoutedEventArgs e)
    {
        this.SetDecorations(new TextRange(this.tb.Selection.Start, this.tb.Selection.End), TextDecorations.Strikethrough);
    }

    private void Baseline(object sender, RoutedEventArgs e)
    {
        this.SetDecorations(new TextRange(this.tb.Selection.Start, this.tb.Selection.End), TextDecorations.Baseline);
    }

    private void Overline(object sender, RoutedEventArgs e)
    {
        this.SetDecorations(new TextRange(this.tb.Selection.Start, this.tb.Selection.End), TextDecorations.OverLine);
    }

    private void SetDecorations(TextRange textRange, TextDecorationCollection decoration)
    {
        var decorations = textRange.GetPropertyValue(Inline.TextDecorationsProperty) as TextDecorationCollection
                          ?? new TextDecorationCollection();

        decorations = decorations.Contains(decoration.First())
                          ? new TextDecorationCollection(decorations.Except(decoration))
                          : new TextDecorationCollection(decorations.Union(decoration));

        textRange.ApplyPropertyValue(Inline.TextDecorationsProperty, decorations);
    }

此代码使用现有装饰集,然后联合或集根据当前装饰是否已附加来排除当前装饰 - 允许切换装饰 on/off。