我设法将其简化为一个简单的测试用例。使用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/