Установка времени разработки DataContext в окне дает ошибку компилятора?

203

У меня есть следующий XAML ниже для главного окна в моем приложении WPF, я пытаюсь установить время разработки d:DataContextниже, что я могу успешно сделать для всех моих различных пользовательских элементов управления, но это дает мне эту ошибку, когда я пытаюсь сделать это на окно...

Error 1 The property 'DataContext' must be in the default namespace or in the element namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'. Line 8 Position 9. C:\dev\bplus\PMT\src\UI\MainWindow.xaml 8 9 UI

<Window x:Class="BenchmarkPlus.PMT.UI.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:UI="clr-namespace:BenchmarkPlus.PMT.UI"
    xmlns:Controls="clr-namespace:BenchmarkPlus.PMT.UI.Controls"
    d:DataContext="{d:DesignInstance Type=UI:MainViewModel, IsDesignTimeCreatable=True}"
    Title="MainWindow" Height="1000" Width="1600" Background="#FF7A7C82">

    <Grid>
        <!-- Content Here -->
    </grid>

</Window>
Джон Эриксон
источник

Ответы:

263

Мне нужно было добавить mc:Ignorable="d"атрибут в тег окна. По сути, я узнал что-то новое. d:Префикс пространства имен , что Expression Blend / Визуальный дизайнер Студия признает фактически игнорируются / «закомментирован» реальным компилятором / XAML анализатор!

<Window 
...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
...
/>

Следующее было взято из

Натан, Адам (2010-06-04). WPF 4 Unleashed (Kindle Locations 1799-1811). Sams. Kindle Edition.

Совместимость разметки

Пространство имен XML совместимости разметки ( http://schemas.openxmlformats.org/markup-compatibility/2006 , обычно используется с mcпрефиксом) содержит атрибут Ignorable, который инструктирует процессорам XAML игнорировать все элементы / атрибуты в указанных пространствах имен, если они не могут быть разрешены к их типам / членам .NET. (Пространство имен также имеет атрибут ProcessContent, который переопределяет Ignorable для определенных типов в игнорируемых пространствах имен.)

Expression Blend использует эту функцию для таких вещей, как добавление свойств времени разработки к содержимому XAML, которые можно игнорировать во время выполнения.

mc:Ignorableможет быть дан список пространств имен, разделенных пробелами, а mc: ProcessContent может быть дан список элементов, разделенных пробелами. Когда XamlXmlReader обнаруживает игнорируемое содержимое, которое не может быть разрешено, он не сообщает о каких-либо узлах для него. Если игнорируемое содержимое может быть разрешено, об этом будет сообщено нормально. Таким образом, потребители не должны делать ничего особенного, чтобы правильно обрабатывать совместимость разметки.

Джон Эриксон
источник
12
Я уже давно бьюсь головой об этом. Имеет смысл, но кажется огромным упущением (объекты данных времени разработки должны поддерживаться без всех этих взломов)
Basic
3
Если вы хотите использовать игнорируемый контекст данных в своем собственном узле вместо атрибута, используйте <d: Window.DataContext />
ChéDon
Отличный совет, выручил меня в странном исключении компилятора. Без mc: ignorable, даже если я установил d: DataContext, компилятор XAML интерпретировал его как попытку установить DataContext и пожаловался на использование неправильного пространства имен xmlns.
Торе Аурстад
19

Вау, какая боль! Будем надеяться, что MS добавит поддержку VS: время разработки для x: Bind.

Мы должны иметь возможность использовать конструктор VS, а также легко переключаться на x: Bind вместо Binding. Вот что я сделал:

  • В моем представлении я добавил свойство для получения моей модели представления. Это имеет смысл, поскольку пути x: Bind относятся к странице (то есть объекту View).

  • На своей странице XAML я добавил следующее <Page ... >в верхней части XAML:

    mc:Ignorable="d" 
    d:DataContext="{d:DesignInstance Type=local:MyView, IsDesignTimeCreatable=False}" 
    DataContext="{x:Bind}"

Таким образом, фактический контекст данных страницы устанавливается на саму страницу из-за {x:Bind}. Это потому, что x:Bindотносится к странице и не указан путь.

В то же время, из-за d:DataContextлинии, конструктор VS размышляет над классом MyView (без создания экземпляра) с целью взаимодействия дизайнера VS. Это позволяет проектировать VS из MyView, где вы можете затем прокрутить вниз до свойства ViewModel, развернуть его и выбрать элемент, с которым вы хотите связать.

Когда вы сделаете все это, конструктор VS создаст оператор Binding, путь которого относительно View, то есть он точно совпадает с путем, ожидаемым x: Bind. Итак, если вы хотите позже переключиться на x: Bind, вы можете просто найти и заменить все " {Binding" на " {x:Bind".

Почему нам даже нужна d:DataContextстрока, чтобы сказать VS, на какой класс смотреть? Хороший вопрос, поскольку вы могли бы подумать, что VS может выяснить, что следующая строка устанавливает DataContext для страницы, используя DataContext={x:Bind}. Попробуйте, это не работает и не работает, если вы измените x: Bind to Binding относительно себя.

Надеюсь, эта ситуация будет исправлена ​​MS!

sjb -
источник
3
WPF не поддерживает x: Bind; этот ответ не будет работать для ОП.
Бэррел Митчелл