É uma boa prática usar controles de usuário para estruturar formulários WPF, mesmo que esses controles sejam usados ​​apenas uma vez?


8

Desenvolvo um aplicativo WPF usando MVVM e estou aprendendo a fazer as coisas melhor.

Eu tenho um formulário WPF com seletores, duas listas com campos de pesquisa e alguns outros elementos. Atualmente, tudo está em uma forma e funciona. Mas agora a VM para esse formulário tem mais de 800 linhas e ainda não está concluída.

Eu quero estruturar este formulário e o código melhor. Pensei em regiões, arquivos com classes parciais e controles de usuário. Eu acho que os controles do usuário seriam melhores porque eles encapsulam alguns controles e lógica. Se eu usasse controles de usuário, a quantidade de código nessa janela e VM seria drasticamente reduzida.

Para fazer isso corretamente, trabalho com o livro "Pro WPF 4.5 In C # 4th Edition", capítulo 18 - Elementos personalizados e o exemplo ColorPickerUserControl. A amostra é sobre um seletor de cores com três controles deslizantes e possui 150 linhas de código.

Acho que entendo como funciona, mas parece-me que criar controles de usuário, mesmo com funcionalidades muito limitadas, como nesse exemplo, é muito trabalhoso . Se eu usasse esses controles várias vezes, entendi que faria sentido fazer isso. Mas se eu usar os controles apenas uma vez e fizer isso apenas para estruturar meu formulário, isso parecerá muito trabalho para pouco ganho.

Minha pergunta é: É uma boa prática usar controles de usuário para estruturar formulários, mesmo que esses controles de usuário sejam usados ​​apenas uma vez? Caso contrário, existe uma alternativa melhor?

Editar (não é necessário ler, apenas mais informações): Até agora não escrevi nenhum detalhe porque queria aprender sobre o princípio, mas depois de ler a resposta interessante de 17 de 26, aqui estão alguns detalhes: Este formulário é para selecionar títulos de músicas.

  • Grupo A: (possível controle de usuário A) refere-se ao tipo de seleção, como selecionar por artista ou álbum, com ou sem vídeo, talvez ano de publicação, etc.

  • Grupo B: Esta lista contém nomes de artistas que são filtrados de acordo com os critérios de A. O usuário pode filtrar a lista, ou seja, mostrando apenas nomes de artistas que contêm "top".

  • Grupo C: Esta lista mostra os títulos do artista selecionado em B também usando os critérios de A (ou seja, áudio ou vídeo). Ele pode ser filtrado de forma semelhante a B, ou seja, apenas títulos contendo "você".

A maior parte da lógica acontece na VM (DataContext do formulário). As listas de A e B vêm de um banco de dados. As listas são filtradas e preparadas para apresentação (ou seja, vários títulos com o mesmo nome, mas em álbuns diferentes). O usuário seleciona um título na C-List clicando duas vezes ou usa arrastar e soltar em outro formulário WPF.

O que eu quero: eu quero código legível para que eu possa alterá-lo facilmente. Se eu quiser adicionar outro filtro, digamos, mostrar apenas artistas femininas, seria bom se eu pudesse apenas ir ao controle de usuário A e adicionar caixas de seleção para artistas masculinos e / ou femininos.

O XAML na forma atual não é um problema, é bem estruturado. Mas a VM possui código para todos os itens acima. Algumas coisas estão no construtor, outras na seção de comandos, algumas propriedades e campos de apoio. Ainda posso encontrar as coisas agora, mas acho que seria melhor se o código fosse mais estruturado. É por isso que penso nos controles do usuário.

Eu tento seguir o MVVM porque acho que a lógica por trás disso faz muito sentido. Mas eu não sou um seguidor fanático de nenhuma prática teórica. Ou seja, se eu puder fazer algo em 5 linhas do CodeBehind ou em 50 linhas na VM, provavelmente o farei no CodeBehind. Minha pergunta é sobre o princípio de como criar formulários estruturados no WPF. O formulário que descrevi acima é um bom exemplo, mas a resposta não deve se concentrar apenas neste, mas na idéia de como estruturar os formulários WPF, isto é, com (ou sem) controles de usuário.

Sobre por que acho que os controles do usuário são muito trabalhosos: eles têm propriedades de dependência, eventos roteados etc. Tudo isso me parece muito mais complicado do que as propriedades "normais" com campos de apoio e INotify. Mas talvez eu apenas precise me acostumar com propriedades de dependência, eventos roteados etc.


Estou um pouco confuso sobre por que você acha que fazer controles de usuário é muito trabalhoso. Na sua forma mais simples, um UserControl é apenas um contêiner. Você faz um como este: <UserControl> </UserControl>. É isso aí.
31718 Robert Harvey

Em relação à sua edição: os controles do usuário têm apenas propriedades de dependência, eventos roteados etc., se você decidir incluir essas coisas. Eles não são obrigatórios, de forma alguma.
31719 Robert Harvey

@RobertHarvey: Sim, eu entendo isso. Mas parece que "funcionalidade completa" com ligação bidirecional, acionando algo na forma principal se algo no controle do usuário foi alterado, etc. eles são necessários. Penso que a amostra do livro que mencionei acima mostra quão necessárias elas frequentemente (nem sempre) são.
Edgar

Você ainda não precisaria fazer tudo isso sem usar os controles do usuário?
Robert Harvey

1
Também não parece que o ViewModel esteja fazendo muito. Classificar e filtrar uma lista de resultados é uma tarefa bastante pequena para um ViewModel. Talvez o problema não seja o que a VM está fazendo, mas como está escrita. Talvez haja alguns recursos de C # que você possa usar para reduzir o tamanho do código. Ou talvez a VM possa ser refatorada para diminuir seu tamanho.
17 de 26

Respostas:


7

Absolutamente sim. É uma boa idéia, da mesma maneira que é uma boa idéia aplicar a separação de preocupações nas classes, para colocar cada uma na sua, a fim de executar uma única tarefa. Você pode ter apenas uma instância dessa classe, mas isso não importa. A otimização não é em termos de desempenho do programa, mas em termos de organização e "integridade" geral do programa.

Você deseja retornar ao seu programa um dia e não precisar percorrer várias centenas de páginas de código, mesmo que ele seja colocado em regiões (usar regiões em classes com muito código é como colocar batom em um porco, pelo caminho). Se você um dia decidir usá-lo em outro lugar, poderá fazê-lo com elegância e sem muitos problemas.

Apenas não tente deixar o controle do usuário acessar o formulário pai. Se você fizer dessa maneira, use eventos para transmitir informações ao pai, com o formulário pai como assinante.


Além disso, quando você cria um controle personalizado, pode encapsular a parte da lógica de apresentação pela qual é responsável, que, se bem feita, tornará sua lógica de apresentação no controle que contém mais simples.
Filip Milovanović

"Absolutamente sim" é uma resposta IMHO não boa quando o esforço para criar um controle de usuário é tão alto quanto o OP o descreve.
Doc Brown

1
Um VIewModel tem uma preocupação única de coordenar a lógica da interface do usuário para um conjunto de controles da interface do usuário. Quebrar isso pode ser um desafio e muitas vezes não faz sentido.
17 de 26

2
@DocBrown A pergunta pede opiniões sobre a prática em geral. Então, acho que a resposta de Neil é justa e uma opinião honesta. Não há resposta absoluta para nada, mas sempre podemos recomendar um lugar para começar. IMHO, se eu estivesse sendo pago para codificá-lo, faria da maneira certa (recomendação de Neil). Além disso - isso pode realmente ajudar a fazer isso se você quiser reutilizar controles em projetos futuros. Mas se eu só quiser brincar ou me fazer algo, eu faria isso da maneira mais rápida, porque já estou atrasada na minha roupa.
Christopher Christopher

1
"absolutamente sim" está incorreto. A resposta certa é "Depende". Ele adiciona custo e complexidade para dividir uma View / VM em várias Views / VMs. O benefício precisa superar o custo.
17 de 26

4

Essa é uma pergunta realmente difícil de responder sem ver o código real. Você também está misturando um pouco os termos. Os controles do usuário não são um mapeamento 1: 1 com o ViewModels.

Os controles do usuário têm um objetivo específico na vida: são uma composição de vários elementos da interface do usuário que são usados ​​como uma unidade juntos. Os controles do usuário são subseções de uma Visualização. Isso é muito diferente de um ViewModel, que contém lógica à qual um View está vinculado.

Talvez faça sentido dividir seu XAML em vários controles de usuário, todos conduzidos por um único ViewModel. Talvez faça sentido dividir seu código XAML e C # em vários pares View-VM. Talvez faça sentido deixar como está agora. Impossível contar sem ver o código em questão.

Qual é o seu objetivo final aqui? O tamanho do código está causando uma dor real ou é apenas para seguir alguma prática teórica?

Você está tentando reduzir o tamanho dos modos de exibição XAML ou o tamanho dos seus modos de exibição em C #? Essas são duas tarefas muito diferentes no mundo do WPF MVVM.

800 linhas não são muito grandes para uma VM que faz backup de uma interface do usuário com qualquer tipo de complexidade. A interrupção de uma VM geralmente pode causar mais problemas do que resolve. Os ViewModels tomam decisões como "desabilite esse recurso quando esta outra lista estiver vazia". Tentar dividir esse tipo de tomada de decisão em vários componentes geralmente não faz sentido e apenas adiciona complexidade ao código.

Agora, com isso dito, pode haver um trabalho que você está fazendo na VM que não tem nada a ver com sua lógica do ViewModel e pode ser facilmente particionado em sua própria classe. Isso reduziria o tamanho do ViewModel sem aumentar a complexidade geral do código.

Eu acho que essa foi apenas uma maneira muito longa de dizer "Depende, e não podemos saber sem ver o código em questão".


Obrigado pela sua resposta. Eu nunca li sobre ter vários pares de View-VM - isso parece uma ideia interessante. De resto, adicionei à minha pergunta.
Edgar

O que é View neste par múltiplo de View-VM(a UserControl/a Grid/a Page ??)
codinome Jack

0

Se eu, que não sabia nada sobre o seu aplicativo, tivesse que adicionar um novo campo sobre o sobrenome ou alterar a ordem de alguns campos ... Acharia fácil ou assustador?

Eu não confio em regiões porque o compilador não verifica se você coloca algo errado na região errada

Você precisa desenvolver software com o objetivo de facilitar o desenvolvimento das pessoas sobre o que você criou.


Você já criou um formulário no WPF? Se sim, você deve saber que faria o que descreve na parte XAML do formulário e não no código por trás ou na VM. Ou, para responder à sua pergunta: Sim, seria muito fácil.
Edgar

@ Edgar A culpa é minha. Você falou sobre componentes visuais e controles de usuário e eu pensei que era tudo. Se todos os seus visuais estiverem na visualização e toda a lógica de negócios no modelo, você não deve se preocupar em ter uma VM longa.
Um Bravo Dev
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.