Conseguir a unidade para resolver visualizações em xaml
-
20-09-2019 - |
Pergunta
Estou começando com o MVVM e estou começando a entender as coisas. Atualmente, estou experimentando a estrutura Cinch, embora ainda não esteja comprometido com isso.
Eu estava injetando os modelos ViewModels nas visualizações usando uma referência ao ViewModel no CodeBehind da visualização, com a propriedade com uma [dependência] dele e no setter que ele define o datacontext para a visualização correta, usando a unidade. Truque legal, pensei.
Estou tentando fazer com que meu aplicativo funcione como uma única janela, com visualizações injetadas (em oposição a várias janelas e lidando com a abertura fechando), mudei minhas opiniões do Windows para UserControls e adicionei A à janela principal. Isso funcionou, mas o viewmodel nunca foi injetado, presumivelmente porque o XAML não usa contêiner.Resolve para criar a visão, como quando eu criei a visualização e a adicionei manualmente no código-behind usando resolução, a [dependência] foi criada .
Como posso configurar minha janela, para que, se eu adicionar uma visão através do XAML, ou a visualização seja alterada como resultado de uma ação da interface do usuário etc., isso é através da unidade, para que possa funcionar sua mágica?
Solução
A maneira de resolver seu problema é fazer com que sua janela também tenha um viewmodel, com o ViewModels of UserControls expõe como propriedades nele. Então, no seu XAML, para uma janela, você simplesmente usaria o mecanismo de ligação para ligar o DataContexts do UserControl às propriedades adequadas do seu model de exibição principal. E como o viewmodel principal é resolvido a partir do contêiner de unidade, ele teria todos os outros viewmodel-s injetados, conforme necessário.
Outras dicas
Esse problema é normalmente resolvido usando regiões e o RegionManager. Na janela principal ViewModel, um conjunto de regiões é criado e adicionado ao RegionManager. Em seguida, o ViewModels pode ser resolvido e adicionado à coleção Região.
No XAML, a região é normalmente injetada por ter a propriedade Itens Source de um itemsControl ligado à propriedade Região do Model ViewModel.
Então, na tela principal ViewModel, você teria algo assim:
public class TestScreenViewModel
{
public const string MainRegionKey = "TestScreenViewModel.MainRegion";
public TestScreenViewModel(IUnityContainer container, IRegionManager regionManager)
{
this.MainRegion = new Region();
regionManager.Regions.Add(MainRegionKey, this.MainRegion);
}
public Region MainRegion { get; set; }
}
Isso seria resolvido normalmente em seu imodule
#region IModule Members
public void Initialize()
{
RegisterViewsAndServices();
var vm = Container.Resolve<SelectorViewModel>();
var mainScreen = Container.Resolve<TestScreenViewModel>();
mainScreen.MainRegion.Add(vm);
var mainView = ContentManager.AddContentView("Test harness", mainScreen);
}
#endregion
E a representação xaml do seu modelo parecendo algo como
<DataTemplate DataType="{x:Type TestModule:TestScreenViewModel}">
<ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto">
<StackPanel>
<ItemsControl ItemsSource="{Binding Path=MainRegion.Views}" />
</StackPanel>
</ScrollViewer>
</DataTemplate>