Ao implementar o ViewModel em um aplicativo WPF da arquitetura Model-View-ViewModel, parece haver duas opções principais de como torná-lo vinculável. Vi implementações que usam DependencyProperty
propriedades que o View vinculará e vi o ViewModel implementando INotifyPropertyChanged
.
Minha pergunta é quando devo preferir um ao outro? Existem diferenças de desempenho? É realmente uma boa idéia atribuir as dependências do ViewModel ao WPF? O que mais preciso considerar ao tomar a decisão de design?
INotifyPropertyChanged
.Respostas:
Kent escreveu um blog interessante sobre esse tópico: Exibir modelos: POCOs versus DependencyObjects .
Pequeno resumo:
Eu prefiro a abordagem POCO. Uma classe base para PresentationModel (também conhecida como ViewModel) que implementa a interface INotifyPropertyChanged pode ser encontrada aqui: http://compositeextensions.codeplex.com
fonte
De acordo com o guia de desempenho do WPF, o DependencyObjects definitivamente tem um desempenho melhor do que os POCOs que implementam INotifyPropertyChanged:
http://msdn.microsoft.com/en-us/library/bb613546.aspx
fonte
A escolha é totalmente baseada na lógica de negócios e no nível de abstração da interface do usuário. Se você não deseja uma boa separação, o DP funcionará para você.
O DependencyProperties será aplicável principalmente no nível VisualElements, portanto, não será uma boa ideia criar um monte de PDs para cada um dos requisitos de negócios. Também há um custo maior para o DP do que um INotifyPropertyChanged. Ao projetar um WPF / Silverlight, tente projetar a interface do usuário e o ViewModel totalmente separados para que, a qualquer momento, possamos alterar os controles de Layout e da interface do usuário (com base no tema e nos estilos)
Consulte também este post - /programming/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel . O link tem muitas referências ao padrão Model-View-ViewModel, o que é muito relevante para esta discussão.
fonte
Do ponto de vista da expressividade, gosto muito de usar propriedades de dependência e me encolher ao pensar nisso
INotifyPropertyChanged
. Além dosstring
nomes das propriedades e possíveis vazamentos de memória devido à assinatura do evento,INotifyPropertyChanged
é um mecanismo muito mais explícito.As propriedades de dependência implicam "quando isso, faça isso" usando metadados estáticos de fácil compreensão. É uma abordagem declarativa que recebe meu voto pela elegância.
fonte
[CallerMemberName]
.INotifyPropertyChanged
quando usado, também permite adicionar mais lógica no código de seus getters e setter de suas propriedades.DependencyProperty
exemplo:No seu getter e setter --- tudo o que você pode fazer é simplesmente chamar SetValue e GetValue, respectivamente, b / c em outras partes da estrutura, o getter / setter não é chamado, mas chama diretamente SetValue, GetValue, portanto sua lógica de propriedade não ser executado com segurança.
Com
INotifyPropertyChanged
, defina um evento:E então simplesmente tenha qualquer lógica em qualquer lugar do seu código e chame:
Isso pode ser em um getter / setter ou em qualquer outro lugar.
fonte
As propriedades de dependência destinam-se a dar suporte à ligação (como destino) nos elementos da interface do usuário e não como uma fonte para a ligação de dados. É aqui que INotifyProperty entra. De um ponto de vista puro, você não deve usar o DP em um ViewModels.
"Para ser a fonte de uma ligação, uma propriedade não precisa ser uma propriedade de dependência; você pode usar qualquer propriedade CLR como uma fonte de ligação. No entanto, para ser o destino de uma ligação, a propriedade deve ser um Para que uma ligação unidirecional ou bidirecional seja eficaz, a propriedade de origem deve suportar notificações de alteração que se propagam para o sistema de ligação e, portanto, para o destino.Para origens de ligação de CLR personalizadas, isso significa que a propriedade deve suportar INotifyPropertyChanged. As coleções devem suportar INotifyCollectionChanged. "
Todos os objetos de dependência não podem ser serializados (isso pode dificultar o uso de ViewModels e DTO (POCO).
Existem diferenças entre o DP no Silverlight e o WPF.
http://msdn.microsoft.com/en-us/library/cc221408(v=VS.95).aspx
http://msdn.microsoft.com/en-us/library/cc903933(VS.95).aspx
fonte
Eu também tive que considerar essa decisão recentemente.
Descobri que o mecanismo INotifyPropertyChanged atendia melhor às minhas necessidades porque me permitia colar minha GUI a uma estrutura de lógica de negócios existente sem duplicar o estado. A estrutura que eu estava usando tinha seu próprio padrão de observador e era fácil encaminhar um nível de notificação para o próximo. Eu simplesmente tive uma classe que implementou a interface do observador da minha estrutura de lógica de negócios e da interface INotifyPropertyChanged.
Com o DP, você não pode definir o back-end que armazena o estado por conta própria. Eu teria que deixar o .net armazenar em cache uma cópia de cada item do estado ao qual estava vinculando. Parecia uma sobrecarga desnecessária - meu estado é grande e complicado.
Então, aqui eu achei INotifyPropertyChanged melhor para expor propriedades da lógica de negócios para a GUI.
Dito isto, onde eu precisava de um widget da GUI personalizado para expor uma propriedade e que as alterações nessa propriedade afetassem outros widgets da GUI, o DP provou ser a solução simples.
Então, lá achei o DP útil para notificação de GUI para GUI.
fonte
O .NET 4.0 terá o System.Xaml.dll, portanto você não precisará depender de uma estrutura arbitrária para utilizá-lo. Veja o post de Rob Relyea sobre sua sessão PDC.
Minha vez
XAML é uma linguagem para descrever objetos e o WPF é uma estrutura cujos objetos descritos são elementos da interface do usuário.
O relacionamento deles é semelhante ao C #, uma linguagem para descrever a lógica, e ao .NET, uma estrutura que implementa tipos específicos de lógica.
O objetivo do XAML são gráficos de objetos declarativos. As tecnologias W * F são ótimas candidatas a esse paradigma, mas o XAML existe independentemente delas.
O XAML e todo o sistema de dependência foram implementados como pilhas separadas para o WF e o WPF, provavelmente para aproveitar a experiência de diferentes equipes sem criar uma dependência (sem trocadilhos) entre elas.
fonte
As propriedades de dependência são a cola da criação de controle personalizado. Se você estiver interessado em usar o Intelli-sense para mostrar suas propriedades na janela de propriedades no tempo de design do XAML, deverá usar as propriedades de Dependência. O INPC nunca mostrará uma propriedade na janela de propriedades em tempo de design.
fonte
Parece que as Propriedades de Dependência devem ser usadas nos controles que você cria, como os Botões. Para usar propriedades em XAML e usar todos os recursos do WPF, essas propriedades devem ser Propriedades de Dependência.
No entanto, seu ViewModel é melhor usando INotifyPropertyChanged. O uso de INotifyPropertyChanged permitirá que você tenha uma lógica getter / setter, se necessário.
Eu recomendo verificar a versão de Josh Smith de uma classe base para um ViewModel que já implementa INotifyPropertyChanged:
http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/
Eu acho que este é um excelente exemplo de como fazer um ViewModel.
fonte
Acho que DependencyProperty e INotifyPropertyChanged são usados para duas coisas diferentes no Binding: o primeiro para permitir que uma propriedade seja o destino de uma ligação e receba a entrada de outra propriedade (use {Binding ...} para definir a propriedade), a última quando você deseja que o valor de uma propriedade seja usado como a origem de uma ligação (nome na Expressão do Caminho de Ligação). Portanto, a escolha é meramente técnica.
fonte
Prefiro uma abordagem mais direta, sobre a qual escrevi no blog no Presentation Model Without INotifyPropertyChanged . Usando uma alternativa à ligação de dados, é possível vincular diretamente às propriedades do CLR sem nenhum código de contabilidade. Você acabou de escrever um código .NET simples no seu modelo de exibição e ele é atualizado quando o modelo de dados é alterado.
fonte
INotifyPropertyChanged
,PropertyDescriptor
são utilizados, o que causa vazamentos de memóriaHá apenas uma coisa por que preferir a
DependencyObject
- A ligação funcionará melhor. Apenas tente um exemplo com uma listaListBox
eTextBox
, preencha com dados daINotifyPropertyChanged
propriedade vs.DependencyProperty
e edite o item atual deTextBox
...fonte
Se você deseja expor propriedades a outros controles, deve usar as propriedades Dependency ... Mas boa sorte, porque elas demoram um pouco para descobrir ...
fonte