Definir o tempo de design do DataContext em uma janela está causando um erro do compilador?

203

Eu tenho o seguinte XAML abaixo para a janela principal do meu aplicativo WPF, estou tentando definir o tempo de design d:DataContextabaixo, o que posso executar com êxito em todos os meus vários UserControls, mas esse erro ocorre quando tento fazê-lo no diretório janela...

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>
Jon Erickson
fonte

Respostas:

263

Eu precisava adicionar o mc:Ignorable="d"atributo à tag Window. Essencialmente, aprendi algo novo. O d:prefixo do namespace que o designer do Expression Blend / Visual Studio reconhece é realmente ignorado / "comentado" pelo compilador real / analisador xaml!

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

O seguinte foi retirado de

Nathan, Adam (04/06/2010). WPF 4 Unleashed (Locais Kindle 1799-1811). Sams. Edição Kindle.

Compatibilidade de marcação

O espaço para nome XML de compatibilidade de marcação ( http://schemas.openxmlformats.org/markup-compatibility/2006 , normalmente usado com um mcprefixo) contém um atributo Ignorable que instrui os processadores XAML a ignorar todos os elementos / atributos nos namespaces especificados, se não puderem. ser resolvido para seus tipos / membros do .NET. (O espaço para nome também possui um atributo ProcessContent que substitui Ignorável por tipos específicos dentro dos espaços para nome ignorados.)

O Expression Blend aproveita esse recurso para fazer coisas como adicionar propriedades em tempo de design ao conteúdo XAML que podem ser ignoradas no tempo de execução.

mc:Ignorablepode receber uma lista de espaços para nome delimitada por espaço e mc: ProcessContent pode receber uma lista de elementos delimitada por espaço. Quando o XamlXmlReader encontra conteúdo ignorável que não pode ser resolvido, ele não informa nenhum nó para ele. Se o conteúdo ignorável puder ser resolvido, ele será relatado normalmente. Portanto, os consumidores não precisam fazer nada de especial para lidar com a compatibilidade de marcação corretamente.

Jon Erickson
fonte
12
Eu tenho batido minha cabeça contra isso por algum tempo. Faz sentido, mas parece ser uma enorme supervisão (objetos de dados em tempo de design deve ser apoiado sem todos estes hacks)
Básico
3
Se você quiser um contexto de dados ignorável em seu próprio nó, como atributo, use <d: Window.DataContext />
ChéDon
Ótima dica, me ajudou a lutar com uma exceção estranha do compilador. Sem mc: ignorable, mesmo se eu definir d: DataContext, o compilador XAML o interpretou como uma tentativa de definir o DataContext e reclamou sobre o uso do namespace xmlns errado.
Tore Aurstad
19

Uau, que dor! Vamos esperar que o MS coloque algum suporte em tempo de design do VS para x: Bind.

Podemos usar o designer do VS, mas também podemos mudar facilmente para x: Bind em vez de Binding. Aqui está o que eu fiz:

  • Na minha visualização, adicionei uma propriedade para obter meu ViewModel. Isso faz sentido porque os caminhos x: Bind são relativos à página (ou seja, o objeto View).

  • Na minha página XAML, adicionei o seguinte <Page ... >na parte superior do XAML:

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

Dessa forma, o contexto de dados reais da página é definido como a própria página devido ao {x:Bind}. Isso x:Bindocorre porque é relativo à página e não há caminho especificado.

Ao mesmo tempo, devido à d:DataContextlinha, o designer do VS reflete na classe MyView (sem criar uma instância) para o objetivo da interação do designer do VS. Isso permite o design do VS no MyView, onde você pode rolar para baixo até a propriedade ViewModel, expandi-la e selecionar o item ao qual deseja vincular.

Quando você faz tudo isso, o designer do VS cria uma instrução Binding cujo caminho é relativo à View, ou seja, é exatamente o mesmo que o caminho que x: Bind espera. Portanto, se você quiser alternar para x: Bind mais tarde, basta pesquisar e substituir todos " {Binding" por " {x:Bind".

Por que precisamos mesmo da d:DataContextlinha para dizer ao VS que classe olhar? Boa pergunta, já que você pensaria que o VS poderia descobrir a próxima linha que define o DataContext para a Página, usando DataContext={x:Bind}. Vá em frente e tente, ele não funciona e nem funciona se você alterar x: Vincular a Vincular em relação a si mesmo.

Espero que esta situação seja resolvida pela MS !!

sjb -
fonte
3
O WPF não suporta x: Bind; esta resposta não funcionará para OP.
Byrel Mitchell