Странная ошибка синтаксического анализа XAML при попытке установить TextBox.IsReadOnly - PullRequest
22 голосов
/ 28 июля 2011

Мне удалось сократить это до простого теста. Исключение выдается при разборе этого 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».

Если я не установлю IsReadOnly на TextBox, он анализируется нормально. Это также хорошо разбирает, если я удаляю триггер стиля.

Может кто-нибудь пролить свет на это? Я довольно новичок в WPF.

UPDATE:
Вот модульный тест, который я использую, чтобы воспроизвести это (он не работает на моем ПК):

[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()!

Ответы [ 4 ]

8 голосов
/ 28 июля 2011

Краткий ответ, ясно, что это ошибка.В качестве обходного пути можно использовать следующее.

Обновление, обходное решение 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
Использование Boolean в mscorlib вместо True в Trigger, похоже, решает проблему навсегда.Следующий 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)
{

}

Я обновлю еще раз, если найду что-нибудь еще об этом ..

3 голосов
/ 05 октября 2012

Один из моих клиентов испытал это на одной установке - я сам не смог его воспроизвести.В моем случае свойство Text было привязано к строковому свойству базовой модели представления, а для свойства IsReadOnly было установлено значение "True" в xaml, как в первом примере из Cameron.

Проблема была решена путем изменения привязки к режиму свойства Text на OneWay.

<TextBox Text="{Binding SomeProperty, Mode=OneWay}" IsReadOnly="True" />
1 голос
/ 06 сентября 2017

У меня была такая проблема со мной в приложении WPF с использованием Telerik UI для WPF 2017.2 с использованием неявных стилей.

Я публикую это здесь, потому что очень вероятно, что другие дойдут до этого вопроса в поисках сообщения об ошибке:

Невозможно установить неизвестного члена 'System.Windows.Controls.TextBox.IsReadOnly'

Обычно XAML неявного стиля конфигурируются с действием сборки «Ресурс», если вы измените его на действие сборки «Страница», все элементы управления Telerik отображаются правильно.

Источник: Страница обратной связи Telerik

Пока мне нужно только изменить действие сборки на Telerik.Windows.Controls.Input.xaml, но ваш пробег может отличаться. По крайней мере, вам не придется менять неявные стили, как я.

PS: я надеюсь, что этот обходной путь проливает свет на любого, кто имеет подобную проблему или пытается исследовать очевидную ошибку в .NET XamlReader

0 голосов
/ 28 июля 2011

XamlParser не будет автоматически загружать дополнительные сборки, такие как System.Windows.Interactivity, в которой определены триггеры. Попробуйте объявить фиктивную переменную из этой сборки в коде перед синтаксическим анализом Xanl. Также можно использовать Assembly.Load для загрузки сборки.

...