22

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

<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>

异常消息是:

无法设置未知成员“System.Windows.Controls.TextBox.IsReadOnly”。行号“13”和行位置“11”。

如果我没有设置IsReadOnlyTextBox它解析得很好。如果我删除样式触发器,它也可以很好地解析。

任何人都可以对此有所了解吗?我对 WPF 比较陌生。

更新:
这是我用来重现这个的单元测试(它在我的电脑上失败了):

[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()or解析时才会失败XamlReader.Load()

4

4 回答 4

9

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

更新,解决方法 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 而不是 TrueTrigger似乎可以永久解决问题。以下 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)
{

}

如果我找到更多关于此的内容,我会再次更新..

于 2011-07-27T22:10:49.633 回答
3

我的一位客户在一次安装中就遇到了这种情况——我自己无法重现。
在我的实例中,该Text属性绑定到底层视图模型的字符串属性,并且该IsReadOnly属性在 xaml 中设置为“True”,就像来自 Cameron 的第一个示例一样。

通过将绑定到Text属性的模式更改为 OneWay 解决了这个问题。

<TextBox Text="{Binding SomeProperty, Mode=OneWay}" IsReadOnly="True" />
于 2012-10-05T06:35:47.767 回答
1

XamlParser 不会自动加载额外的程序集,例如定义触发器的 System.Windows.Interactivity。在解析 Xanl 之前,尝试在代码中从该程序集中声明一个虚拟变量。或者,使用 Assembly.Load 加载程序集。

于 2011-07-27T21:17:08.063 回答
1

我在使用 Telerik UI for WPF 2017.2 使用隐式样式的 WPF 应用程序上遇到了这个问题。

我在此处发布此内容是因为其他人很可能会遇到此问题以查找错误消息:

无法设置未知成员“System.Windows.Controls.TextBox.IsReadOnly”

通常,隐式样式 XAML 配置为“资源”的构建操作,如果将其更改为构建操作“页面”,则所有 Telerik 控件都会正确显示。

来源:Telerik 反馈页面

到目前为止,我只需要更改 Telerik.Windows.Controls.Input.xaml 上的构建操作,但您的里程可能会有所不同。至少您不必像我一样更改隐式样式。

PS:我希望这个解决方法能够为任何有类似问题或正在尝试调查 .NET XamlReader 上的明显错误的人提供一些启示

于 2017-09-05T21:53:14.193 回答