terça-feira, 7 de junho de 2011

Entity Framework NavigationProperties e a Interface INotifyPropertyChanging

O WPF assim como o Silverlight usam o evento PropertyChanging da interface INotifyPropertyChanging para atualizar os bindings dos controles.
As entidades do EntityFramework ja tratam isso pra você, por isso você não tem que se preocupar, veja um exemplo:

[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
[DataMemberAttribute()]
public string Nome
{
     get
    {
           return _Nome;
     }
     set
    {
           OnNomeChanging(value);
            ReportPropertyChanging("Nome");
           _Nome= StructuralObject.SetValidValue(value);
           ReportPropertyChanged("Nome");
           OnNomeChanged();
      }
}

Porém, quando se há um relacionamento como, por exemplo, uma pessoa possui várias compras, e você está trabalhando com a entidade Compra, se você fizer:

compra.Pessoa = pessoa;
e caso o seu TextBox esteja com o binding para o Nome da Pessoa relacionado:

<TextBox Text="{Binding Pessoa.Nome}" />

o texto do TextBox não será atualizado porque não há eventos que notifique essa mudança, veja como é implementado o get e o set de Pessoa:

[XmlIgnoreAttribute()]
[SoapIgnoreAttribute()]
[DataMemberAttribute()]
[EdmRelationshipNavigationPropertyAttribute("Model", "FK__Pessoa_Compra", "Pessoa")]
public Pessoa Pessoa
{
      get
      {
             return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Pessoa>("Model.FK__Pessoa_Compra", "Pessoa").Value;
       }
       set
      {
            ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Pessoa>   ("Model.FK__Pessoa_Compra", "Pessoa").Value = value;
       }
}

Por sorte, o EntityFramework possui eventos que você pode utilizar para reverter esta situação.
Para toda referência há uma ou mais propriedades que se relacionam entre as tabelas, e com isso elas também existem nas entidades do EntityFramework. No meu caso há uma coluna chamada IdPessoa do tipo int na entidade Compra. Essas colunas são atualizadas assim que você atribui a nova pessoa na referência, desta maneira se a pessoa tiver o Id = 15, o compra.IdPessoa também será 15 quando eu fizer:
compra.Pessoa = pessoa, e todos os eventos PropertyChanging e PropertyChanged serão disparados.
Dessa maneira podemos usar o evento parcial dessa coluna para notificar nossa interface da mudança dos valores:

public partial class Compra
{
      partial void OnIdPessoaChanged()
     {
           OnPropertyChanged("Pessoa");
      }
      partial void OnIdPessoaChanging(int value)
     {
           OnPropertyChanging("Pessoa");
     }
}

Repare que a string passada como parâmetro é Pessoa que é o nome da nossa propriedade de relacionamento.
Note também que esta classe deve estar no mesmo namespace da classe gerada pelo EntityFramework.

Até a próxima.

Nenhum comentário:

Postar um comentário