以编程方式向 TextBlock 添加文本装饰会导致 InvalidOperationException

Programatically adding a TextDecoration to a TextBlock causes InvalidOperationException

我正在尝试通过数据绑定将 TextDecoration(例如删除线)添加到 TextBlock 属性。

最小示例:

public partial class TextDecoTest : Window
    {
        public TextDecoTest()
        {
            DataContext = this;
            InitializeComponent();
            TextDeco.Add(TextDecorations.Strikethrough); //Exception here
        }    


        public TextDecorationCollection TextDeco
        {
            get { return (TextDecorationCollection)GetValue(TextDecoProperty); }
            set { SetValue(TextDecoProperty, value); }
        }    

        public static readonly DependencyProperty TextDecoProperty =
            DependencyProperty.Register("TextDeco", typeof(TextDecorationCollection), typeof(TextDecoTest), new PropertyMetadata(new TextDecorationCollection()));


    }

XAML:

<Window>
    <TextBlock Text="Test" TextDecorations="{Binding TextDeco}" />
</Window>

但是,添加 TextDecoration 失败:

Specified value of type 'System.Windows.TextDecorationCollection' must have IsFrozen set to false to modify.

好的,但是由于您不能真正解冻 WPF 中的控件,所以我有点难过。如果我创建一个新的 TextDecorationCollection,添加装饰然后替换整个集合,它会起作用,但这在我们的例子中并不可行,而且感觉不对。 我发现其他几个提到这个问题的地方,但它们似乎指的是 .NET 4.5 已修复的错误(我们使用的是 4.6.1)。

TextDecorationsclass中的四个静态属性已经是TextDecorationCollection类型,例如

public static TextDecorationCollection Strikethrough { get; }

显然它们不能合并。

因此,不要将它们中的任何一个添加到您的 TextDeco 属性,只需像这样设置 属性:

TextDeco = TextDecorations.Strikethrough;

然而,您可以像这样组合两个 TextDecorations:

TextDeco = new TextDecorationCollection(
    Enumerable.Concat(TextDecorations.Strikethrough, TextDecorations.Underline));

或更多,通过递归调用 Concat:

TextDeco = new TextDecorationCollection(
    Enumerable.Concat(TextDecorations.Strikethrough,
        Enumerable.Concat(TextDecorations.Underline, TextDecorations.OverLine)));