Quais abordagens estão disponíveis para dados de tempo de design fictícios no WPF?

97

Estou trabalhando sem mistura de expressão e usando apenas o editor XAML no vs2010. Deixando isso de lado, vejo cada vez mais a necessidade de vinculação de dados em tempo de design. Para casos simples, a FallbackValuepropriedade funciona muito bem (Textboxes e TextBlocks, etc). Mas, especialmente ao lidar com ItemsControle semelhantes, é necessário que os dados de amostra fiquem visíveis no designer para que você possa ajustar e ajustar os controles e modelos de dados sem ter que executar o executável.

Eu sei que isso ObjectDataProviderpermite a vinculação a um tipo e, portanto, pode fornecer dados de tempo de design para visualização, mas há alguns malabarismos para permitir que os dados de tempo de execução reais sejam vinculados sem desperdiçar recursos ao carregar o tempo de design, dados simulados e as ligações de tempo de execução.

Na verdade, o que desejo é a capacidade de ter, digamos, "John", "Paul", "George" e "Ringo" no designer XAML como itens estilizáveis ​​no meu ItemsControl, mas dados reais aparecerem quando o aplicativo corre.

Eu também sei que o Blend permite alguns atributos sofisticados que definem dados de vinculação de tempo de design que são efetivamente ignorados pelo WPF em condições de tempo de execução.

Então, minhas perguntas são:

1. Como posso aproveitar as associações de tempo de design de coleções e dados não triviais no designer XAML do Visual Studio e, em seguida, trocar para associações de tempo de execução sem problemas?

2. Como outras pessoas resolveram esse problema de dados em tempo de design vs. tempo de execução? No meu caso, não posso usar facilmente os mesmos dados para ambos (como seria possível com, digamos, uma consulta de banco de dados).

3. Existem alternativas para a combinação de expressões que eu poderia usar para o design XAML integrado de dados? (Eu sei que existem algumas alternativas, mas eu quero especificamente algo que eu possa usar e ver dados de amostra vinculados, etc?)

el2iot2
fonte

Respostas:

120

Usando VS2010, você pode usar atributos de tempo de design (funciona para SL e WPF). Eu geralmente tenho uma fonte de dados simulada de qualquer maneira, então é só uma questão de:

  • Adicionando a declaração de namespace

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  • Adicionando o contexto de dados fictícios aos recursos de janela / controle

    <UserControl.Resources>
      <ViewModels:MockXViewModel x:Key="DesignViewModel"/>
    </UserControl.Resources>
  • Definição do contexto de dados em tempo de design

    <Grid d:DataContext="{Binding Source={StaticResource DesignViewModel}}" ...

Funciona bem o suficiente.

Goran
fonte
2
Se estiver tendo problemas para usar, d:DataContextvocê pode encontrar ajuda nesta questão: stackoverflow.com/questions/8303803/…
Martin Liversage
27
Este exemplo não faria com que uma instância de MockXViewModel fosse carregada em seus recursos para uma versão de lançamento? Isso não é uma preocupação?
jpierson
12
Para sua informação: você também precisa do seguinte, ou o compilador VS2012 não compilará o arquivo xaml: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"emc:Ignorable="d"
Orion Edwards
51
jpierson está certo. Eu prefiro usar <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" .... Dessa forma, o modelo de visão simulado só será criado no designer, não durante a execução de seu aplicativo. Lembre-se de que essa abordagem requer que seu modelo de visualização simulada tenha um construtor sem parâmetros. Mas o mesmo é o caso no exemplo dado acima na resposta.
René
2
@ René sua abordagem é muito melhor. Por favor, adicione-o como uma resposta e eu votarei a favor
dss539
15

Como um amálgama da resposta aceita de Goran e do excelente comentário de René.

  • Adicione a declaração de namespace. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

  • Referencie seu contexto de dados de tempo de design do código.
    <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...

John Stritenberger
fonte
1
Estou tentado a marcar isso como a nova resposta, mas talvez possamos extrair o resto dos detalhes.
el2iot2
Isso precisa de mais visibilidade ou precisa ser incluído na resposta aceita. É uma solução muito melhor.
Lauraducky
Por que isso é melhor? A princípio pensei que a resposta aceita produziria desnecessariamente modelos de simulação também em tempo de execução, mas testei isso e de fato não o fez. Os recursos não são criados se não forem usados.
Paul
@Paul É realmente uma questão de preferência, mas essa resposta mantém todo o contexto dos dados de tempo de design em uma declaração em vez de tê-lo em dois pontos. Facilita as mudanças
John Stritenberger
1
@JohnStritenberger Não é apenas preferência, a resposta aceita carrega recursos desnecessariamente na memória para todo o tempo, não apenas para o designer.
UuDdLrLrSs
4

Karl Shifflett descreve uma abordagem que deve funcionar igualmente bem para VS2008 e VS2010:

Visualizando dados de tempo de design no Visual Studio 2008 Cider Designer em projetos WPF e Silverlight

Laurent Bugnion tem uma abordagem semelhante que se concentra no Expression Blend. Ele pode trabalhar para VS2010, mas eu não confirmaram isso ainda.

Simular dados no modo de design no Microsoft Expression Blend

dthrasher
fonte
obrigado por trazer isso à minha atenção. Eu gosto do conceito DesignAndRunTimeDataContext.
el2iot2
1
Karl Shifflett tem um artigo atualizado para o Visual Studio 2010: Dados de amostra no WPF e Silverlight Designer
totorocat
1
A essência do conteúdo do link realmente deve ser editada na resposta, especialmente porque o primeiro link agora está morto.
Lauraducky
4

Talvez os novos recursos de tempo de design do Visual Studio 2010 e Expression Blend 4 sejam uma opção para você.

Como funciona é mostrado no aplicativo de amostra BookLibrary do WPF Application Framework (WAF) . Faça download da versão .NET4.

jbe
fonte
Obrigado pelo link. Existe um arquivo de código ou construção em particular que devo examinar para ver a abordagem? (uma breve visão geral seria ótimo)
el2iot2
Dê uma olhada no projeto BookLibrary.Presentation. Neste projeto você encontra a pasta "DesignData" que é usada pelos UserControls na pasta "Views".
JBE
1
+1. Acabei de dar uma olhada nisso. Para qualquer pessoa interessada, o modelo de exibição de dados de amostra é declarado em XAML e referenciado via d: DataContext = "{d: DesignData Source = .. / DesignData / SampleLendToViewModel.xaml}"
RichardOD
4

Eu uso essa abordagem para gerar dados de tempo de design com .NET 4.5 e Visual Studio 2013.

Eu tenho apenas um ViewModel. O modelo de visualização possui uma propriedade IsInDesignModeque informa se o modo de design está ativo ou não (consulte a classe ViewModelBase). Em seguida, você pode configurar seus dados de tempo de design (como preencher um controle de itens) no construtor de modelos de visualização.

Além disso, eu não carregaria dados reais no construtor de modelos de visualização, isso pode levar a problemas no tempo de execução, mas configurar os dados para o tempo de design não deve ser um problema.

public abstract class ViewModelBase
{
    public bool IsInDesignMode
    {
        get
        {
            return DesignerProperties.GetIsInDesignMode(new DependencyObject());
        }
    }
}

public class ExampleViewModel : ViewModelBase
{
    public ExampleViewModel()
    {
        if (IsInDesignMode == true)
        {
            LoadDesignTimeData();
        }
    }

    private void LoadDesignTimeData()
    {
        // Load design time data here
    }       
}
Martin
fonte
4

Usando o Visual Studio 2017, tenho tentado seguir todos os guias e questões como esta e ainda estava diante de um <ItemsControl>que simplesmente não executou o código que eu tinha dentro do construtor de um do DesignFooViewModelqual herda FooViewModel. Confirmei a parte "não executou" seguindo este guia "útil" do MSDN (spoiler: MessageBoxdepuração). Embora isso não esteja diretamente relacionado à pergunta original, espero que poupe muito tempo aos outros.

Acontece que não estava fazendo nada de errado. O problema era que meu aplicativo precisava ser construído para x64. Como o Visual Studio ainda é em 2018 um processo de 32 bits e aparentemente não pode girar um processo de host de 64 bits para a parte do designer, ele não pode usar minhas classes x64. O que é realmente ruim é que não há erros em nenhum log que eu possa imaginar.

Portanto, se você se deparar com essa pergunta porque está vendo dados falsos em seu modelo de visualização do tempo de design (por exemplo: <TextBlock Text="{Binding Name}"/>aparece Nameindependentemente de você definir a propriedade como), a causa provavelmente será sua construção x64. Se você não puder alterar sua configuração de compilação para anycpu ou x86 por causa das dependências, considere a criação de um novo projeto que seja totalmente anycpu e não tenha as dependências (ou quaisquer dependências). Então, você acaba dividindo a maior parte ou todas, exceto as partes de inicialização do código, de seu projeto "WPF App" em um projeto de "biblioteca de classes C #".

Para a base de código em que estou trabalhando, acho que isso forçará uma separação saudável de interesses ao custo de alguma duplicação de código, o que provavelmente é positivo.

joonas
fonte
3

Semelhante à resposta mais bem avaliada, mas melhor na minha opinião: você pode criar uma propriedade estática para retornar uma instância de dados de design e referenciá-la diretamente do XAML assim:

<d:UserControl.DataContext>
    <Binding Source="{x:Static designTimeNamespace:DesignTimeViewModels.MyViewModel}" />
</d:UserControl.DataContext>

Isso evita a necessidade de uso UserControl.Resources. Sua propriedade estática pode funcionar como uma fábrica, permitindo que você construa tipos de dados não triviais - por exemplo, se você não tiver um ctor padrão, você pode chamar uma fábrica ou contêiner aqui para injetar nas dependências apropriadas.

Jack Ukleja
fonte