我设法将其简化为一个简单的测试用例。使用XamlReader.Parse()解析此XAML期间会引发异常:

<DockPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DockPanel.Resources>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="IsReadOnly" Value="True">
                    <Setter Property="Background" Value="#FFEEEEEE" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </DockPanel.Resources>


    <TextBox IsReadOnly="True" />
</DockPanel>

异常消息是:



如果我没有在IsReadOnly上设置TextBox,它会很好解析。如果删除样式触发器,它也可以解析。

谁能对此有所启发?我是WPF的新手。

更新:
这是我用来重现此内容的单元测试(在我的PC上失败):
[TestMethod]
public void TestIsReadOnlyOnTextBox()
{
    // Arrange
    var xaml =
@"<DockPanel xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
    <DockPanel.Resources>
        <Style TargetType=""TextBox"">
            <Style.Triggers>
                <Trigger Property=""IsReadOnly"" Value=""True"">
                    <Setter Property=""Background"" Value=""#FFEEEEEE"" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </DockPanel.Resources>


    <TextBox IsReadOnly=""True"" />
</DockPanel>
";

    // Act
    try {
        var root = XamlReader.Parse(xaml);
    }
    catch (XamlParseException ex) {
        Assert.Fail(ex.Message);
    }

    // If we get here, test passes
}

更新2:
我最初只引用PresentationFramework v4.0.30319。添加对PresentationCore,System.Xaml和WindowsBase的引用无效。

项目的.NET版本为4(完整,不是客户端配置文件)。

更新3:
Arg,这在ExpressionBlend 3.0.1927.0和XamlPadX 4中可以正常工作。正如AresAvatar报道的那样,它似乎只有在用XamlReader.Parse()XamlReader.Load()解析时才会失败!

最佳答案

简短的回答,显然这是一个错误。以下可以用作解决方法。

更新,解决方法2

即使只是在XamlReader.Parse(xaml)之前执行以下行即可解决该问题,尽管如此仍然毫无头绪。

XamlReader.Parse(@"<TextBox xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
                            xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
                            IsReadOnly=""True""/>");
var root = XamlReader.Parse(xaml);

解决方法1
在mscorlib中使用Boolean而不是Trigger中的True似乎可以彻底解决此问题。以下xaml不会在XamlReader.Parse中引发异常
var xaml =
@"<DockPanel xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
             xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
             xmlns:s=""clr-namespace:System;assembly=mscorlib"" >
    <DockPanel.Resources>
        <s:Boolean x:Key=""BooleanTrue"">True</s:Boolean>
        <Style TargetType=""TextBox"">
            <Style.Triggers>
                <Trigger Property=""IsReadOnly"" Value=""{StaticResource BooleanTrue}"">
                    <Setter Property=""Background"" Value=""#FFEEEEEE"" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </DockPanel.Resources>
    <TextBox IsReadOnly=""True"" />
</DockPanel>";

一些研究细节

我对这个奇怪的问题做了一些测试。

首先,我将工作的DockPanel包含在Xaml中,并保存为
string xaml = XamlWriter.Save(theDockPanel);

只是为了查看该xaml是否与XamlReader.Parse一起使用,并且确实如此。

然后,我对生成的xaml进行了微小的更改(一旦异常返回,将其还原),直到与原始位置尽可能接近。奇怪的是,一旦解析了此xaml,原始文件也将起作用。

使它起作用的部分似乎是使用<s:Boolean>True</s:Boolean>而不是True
var modifiedXaml = @"<DockPanel xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
                                xmlns:s=""clr-namespace:System;assembly=mscorlib""
                                xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
                <DockPanel.Resources>
                    <s:Boolean x:Key=""BooleanTrue"">True</s:Boolean>
                    <Style TargetType=""TextBox"">
                        <Style.Triggers>
                            <Trigger Property=""IsReadOnly"" Value=""{StaticResource BooleanTrue}"">
                                <Setter Property=""Background"" Value=""#FFEEEEEE"" />
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </DockPanel.Resources>
                <TextBox IsReadOnly=""True"" />
            </DockPanel>";

var originalXaml = @"<DockPanel xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
                                xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
                <DockPanel.Resources>
                    <Style TargetType=""TextBox"">
                        <Style.Triggers>
                            <Trigger Property=""IsReadOnly"" Value=""True"">
                                <Setter Property=""Background"" Value=""#FFEEEEEE"" />
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </DockPanel.Resources>
                <TextBox IsReadOnly=""{Binding}""/>
            </DockPanel>";
try
{
    // If this line is executed, no `XamlParseException` is thrown
    var root = XamlReader.Parse(modifiedXaml);
    var root2 = XamlReader.Parse(originalXaml);
}
catch (XamlParseException ex)
{

}

如果我发现更多相关信息,我将再次更新。

关于c# - 尝试设置TextBox.IsReadOnly时出现奇怪的XAML分析错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6850713/

10-10 08:16