Pergunta

Estou desenvolvendo um aplicativo WinForms (.Net 3.5, sem WPF) onde desejo poder exibir pesquisas de chave estrangeira em um DataGridView de ligação de dados.

Um exemplo desse tipo de relacionamento é que tenho uma tabela de OrderLines.As Orderlines têm um relacionamento de chave estrangeira com Produtos e os Produtos, por sua vez, têm um relacionamento de chave estrangeira com ProductTypes.

Eu gostaria de ter um DataGridView de ligação de dados em que cada linha representasse uma linha de pedido, exibindo o produto e o tipo de produto da linha.

Os usuários podem adicionar ou editar linhas de pedido diretamente na grade e escolher o produto para a linha de pedido em um comboBoxColumn - isso deve atualizar a coluna producttype, mostrando o producttype do produto selecionado, na mesma linha.

O mais próximo de um bom ajuste que encontrei até agora é introduzir um objeto de domínio que representa uma linha de pedido e, em seguida, vincular o DataGridView a uma coleção dessas linhas de pedido.Em seguida, adiciono propriedades ao objeto orderline que expõem o produto e o producttype e gero eventos notifypropertychanged relevantes para manter tudo atualizado.Em meu repositório de linha de pedido, posso conectar os mapeamentos entre esse objeto de linha de pedido e as três tabelas em meu banco de dados.

Isso funciona para o lado da ligação de dados, mas ter que codificar manualmente todo aquele mapeamento OR no repositório parece ruim.Achei que o nHibernate seria capaz de ajudar com essa fiação, mas estou lutando com os mapeamentos através de todas as chaves estrangeiras - elas parecem funcionar bem (a pesquisa de chave estrangeira para o produto de uma linha de pedido cria o objeto de produto correto com base na chave estrangeira) até que eu tento fazer a ligação de dados, não consigo fazer com que as colunas de identificação de ligação de dados atualizem meus objetos produto ou tipo de produto.

Minha abordagem geral está correta?Se for, qual é uma boa solução para o problema de mapeamento?

Ou existe uma solução melhor para linhas de ligação de dados, incluindo pesquisas de chave estrangeira que eu nem considerei?

Foi útil?

Solução

Acho que o problema que você está enfrentando é que quando você está vinculando a uma grade, não é suficiente suportar INotifyPropertyChanged, mas você precisa disparar os eventos ListChanged em seu IBindingList implementação e certifique-se de substituir e retornar true para o Suporta Notificação de Mudança propriedade.Se você não retornar verdadeiro para isso, a grade não irá procurar para saber se os dados foram alterados.

No .NET 2.0+, você pode criar uma coleção genérica usando o Lista de Ligações class, isso cuidará da maior parte da maldade (só não se esqueça de substituir e retornar true para a propriedade SupportsChangeNotification).

Se a classe usada para vinculação de dados tiver uma propriedade que seja uma coleção (como IBindingList ou BindingList), você poderá vincular a grade de chave estrangeira diretamente a essa propriedade.Ao configurar as ligações no designer de Formulários, basta selecionar a propriedade da coleção como a fonte de dados da grade.Deveria "simplesmente funcionar".A única parte furtiva é garantir que você lide com coleções vazias ou nulas da maneira certa.

Outras dicas

bem-vindo ao StackOverflow :)

Normalmente o que você faria é basear as informações no menu suspenso em dois valores ValueMember e DisplayMember.

O ValueMember é a fonte do valor real dos controles (este será o valor chave na linha do pedido), o membro de exibição é o valor que é exibido ao usuário em vez do valor (este será o valor FK).

Não há nenhum motivo específico para você não poder simplesmente retornar todos os dados necessários e definir essas propriedades?

Aqui está um bom vídeo "Como fazer" que demonstra a vinculação de dados:

http://windowsclient.net/learn/video.aspx?v=52579

Bem, não sei se é suportado pelo DataGridView, mas quando você está fazendo uma ligação de dados regular do WinForms (digamos, para um TextBox normal), você pode usar caminhos de propriedade para navegar pelos relacionamentos de objetos.

Algo assim:

myTextBox.DataBindings.Add("Text", anOrderLine, "OrderedPart.PartNumber");

Valeria a pena ver se isso funciona na sua situação também.

Minha pergunta original obviamente não estava clara, desculpe por isso.

O problema não era com a ligação de dados a um DataGridView em geral, ou com a implementação de um DataGridViewComboBoxColumn - como dizem as pessoas que responderam com razão, isso está bem documentado na web.

O problema que estou tentando resolver é com a atualização de propriedades que detalham os relacionamentos.

No meu exemplo de pedidos, quando altero o valor da coluna "Produto", a coluna "Tipo de Produto" não está sendo atualizada - mesmo que no código eu esteja configurando a propriedade e disparando o evento NotifyPropertyChanged.(Na depuração eu vou para todos os lugares certos)

Depois de muita pesquisa, percebi que isso nem estava funcionando quando defini diretamente a propriedade "Tipo de produto" da fonte de dados, em vez de defini-la no setter "Produto".

A outra coisa que acredito que me colocou de volta no caminho certo é que quando forneço uma camada de acesso a dados simulada, criada no formulário principal, tudo funciona bem.

Além disso, quando copio o IList feito pelo nHibernate para um IBindingList - tudo novamente parece bem.

Então o problema é que acho que o threading e os eventos NotifyPropertyChanged são perdidos ao usar determinadas fontes de dados, de certas maneiras (gostaria de ser mais definitivo do que isso!)

Continuarei pesquisando maneiras melhores de resolver isso do que copiar o IList para o IBindingList - talvez eu precise aprender sobre empacotamento de threads.

Editar

Agora desenvolvi uma solução que resolve o problema e acho que entendo o que estava me confundindo - basicamente parece que qualquer coisa que não seja a ligação de dados de propriedades básicas não funciona bem para listas que não são derivadas de BindingList - assim que eu estava tentando para vincular dados a propriedades que dispararam eventos NotifyPropertyChanged encadeados, as coisas deram errado e meus eventos se perderam.

A solução de acesso a dados que tenho agora usa uma variação do Rob Conery IRepositório padrão, retornando minhas coleções para serem vinculadas como uma classe customizada que fiz, uma SortableBindingLazyList que deriva de BindingList, implementa os métodos Sort Core e também armazena sua lista interna como uma consulta, atrasando a materialização da lista.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top