簡體   English   中英

嘗試設置TextBox.IsReadOnly時出現奇怪的XAML解析錯誤

[英]Weird XAML parsing error when trying to set TextBox.IsReadOnly

我已經設法將其簡化為一個簡單的測試用例。 使用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>

異常消息是:

無法設置未知成員'System.Windows.Controls.TextBox.IsReadOnly'。 行號'13'和行位置'11'。

如果我沒有在TextBox上設置IsReadOnly ,它會解析得很好。 如果我刪除樣式觸發器,它也會解析。

任何人都可以對此有所了解嗎? 我對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()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
Trigger使用mscorlib中的布爾而不是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>";

一些研究細節......

我對這個奇怪的問題做了一些測試。

首先,我在Xaml中包含了工作的DockPanel並將其保存

string xaml = XamlWriter.Save(theDockPanel);

只是為了看看那片xaml是否正在使用XamlReader.Parse ,它確實如此。

然后我對生成的xaml進行了小的更改(並在異常返回后恢復),直到我盡可能接近原始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)
{

}

如果我發現更多內容,我會再次更新..

我的一位客戶在一次安裝中遇到過這種情況 - 我無法自己復制。
在我的實例中, Text屬性綁定到底層視圖模型的字符串屬性,並且在xaml中IsReadOnly屬性設置為“True”,如Cameron的第一個示例中所示。

通過將綁定到Text屬性的模式更改為OneWay來解決該問題。

<TextBox Text="{Binding SomeProperty, Mode=OneWay}" IsReadOnly="True" />

我使用隱式樣式使用Telerik UI for WPF 2017.2在WPF應用程序上遇到此問題。

我在這里發布這個是因為其他人很可能會在查找錯誤消息時遇到此問題:

無法設置未知成員'System.Windows.Controls.TextBox.IsReadOnly'

通常,隱式樣式XAML使用“資源”的構建操作進行配置,如果將其更改為構建操作“頁面”,則所有Telerik控件都會正確顯示。

來源: Telerik反饋頁面

到目前為止,我只需要更改Telerik.Windows.Controls.Input.xaml上的構建操作,但您的里程可能會有所不同。 至少你不必像我那樣改變隱式樣式。

PS:我希望這個解決方法可以解決任何有類似問題的人,或者試圖調查.NET XamlReader上的明顯錯誤

XamlParser不會自動加載額外的程序集,例如System.Windows.Interactivity,這是定義觸發器的位置。 在解析Xanl之前,嘗試在代碼中聲明來自該程序集的虛擬變量。 或者,使用Assembly.Load加載程序集。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM