É um ViewModel 'Deus' desejado no WPF

5

Meu aplicativo tem controles de usuário dentro dos controles de usuário. Por favor, veja uma captura de tela de uma das mais belas aplicações de todos os tempos (UC = controle de usuário):

TodasaspropriedadesestãonocódigoMainWindow,nãohánenhumaemmeusUserControls.Paraligaràsminhaspropriedadeseuuso

DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1,AncestorType=Window}}"

Isso funciona bem, mas significa que todas as propriedades de ligação estão no meu código MainWindow (ou no MainWindow ViewModel).

Isso é desejado em uma abordagem MVVM (ou devo dizer WPF), em que todas as crianças compartilham o mesmo ViewModel?

    
por Dave 06.12.2013 / 10:03
fonte

2 respostas

6

Eu acho que é uma prática ruim ter um God ViewModel, o ViewModel mais alto, vamos chamá-lo de MainWindowViewModel , só deve conter dados e comportamento acoplados ao da MainWindow, que geralmente é muito fino, todos os outros trabalhos devem ser delegados para submodelos.

Se você tiver um gerenciador de ancoragem ou outra lógica de gerenciador de janelas, esse código deve residir no MainWindowViewModel .

Aqui está um exemplo de um ViewModel que eu fiz que delega o comportamento a submodelos

link

Eu não acho que seja uma boa prática passar dados para submodelos, isso cria dependências entre modelos. É melhor usar um padrão de agregação de eventos, dessa forma todos os modelos interessados em alterações de dados podem se inscrever no evento.

Update : Eu fiz uma melhoria no meu modelo de janela principal, em vez de o construtor pegar todos os modelos de sub view, agora ele pega uma coleção de viewmodels. E então eu configuro o IoC para injetar modelos corretos

private void ConfigurePanels()
{
    kernel.Bind<PanelViewModel>().To<ConsoleViewModel>();
    kernel.Bind<PanelViewModel>().To<ErrorsViewModel>();
    kernel.Bind<PanelViewModel>().To<WatchesViewModel>();
}

Isso torna o modelo principal um pouco menos acoplado aos submodelos, antes da mudança

    public MainShellViewModel(ConsoleViewModel consoleViewModel,
                              ErrorsViewModel errorsViewModel,
                              WatchesViewModel watchesViewModel
        )
        : base(resultFactory)
    {            
        Tools = new BindableCollection<PanelViewModel> {consoleViewModel, errorsViewModel, watchesViewModel};
    }

e depois

    public MainShellViewModel(IEnumerable<PanelViewModel> panels)
        : base(resultFactory)
    {
        Tools = new BindableCollection<PanelViewModel> (panels);
    }

link

    
por 13.01.2014 / 14:13
fonte
1

A menos que seja sobrescrito, os controles filhos herdarão o DataContext (exceto os filhos de um ItemsControl).

Se você não está definindo explicitamente o DataContext em todos os seus controles, você deve estar bem (mas seu acoplamento é alto ... ou seja, seu usercontrol agora assume que ele será usado apenas em uma configuração específica)

Se você estiver definindo explicitamente o DataContext, isso se tornará um problema de Injeção de Dependência. Se um grand-grand-grandchild usercontrols requer dados do topmost viewmodel, então esses dados provavelmente devem ser passados para o viewmodel de nível mais próximo. Pense nisso. Esses dados são claramente uma dependência do ViewModel ligado ao UserControl.

    
por 06.12.2013 / 12:10
fonte

Tags