locked
Databind datagrid e textbox RRS feed

  • Pergunta

  • Pessoal,

    tenho a seguinte situação.

    uma tela com 2 textbox.....Nome e Email.

    1 datagrid com apenas as colunas Nome e Id (sem a coluna Email mesmo).

    1 classe Clientes

    1 classe Cliente

    preenchi com databind (pelo DataContext) o datagrid com a classe Clientes......

    eu gostaria que ao selecionar um cliente no grid......a classe Cliente seja preenchida com este registro (procurado na classe Clientes no evento SelectionChanged do grid).......

    e os campos textbox sejam preenchidos com os valores da classe Cliente preenchida acima (no SelecitionChanged) fazendo o DataBind........

    alguém sabe como fazer isto ????

     

    Abs,


    Lucas Giusti
    quarta-feira, 13 de outubro de 2010 03:40

Respostas

  • Lucas,

    Uma maneira é utilizar a classe CollectionViewSource e então não necessitar do código para tratar o evento SelectionChanged. Para isso, siga os seguintes passos (ou faça algo parecido).

    1 - Defina um resource para a classe CollectionViewSource no XAML.

    <UserControl.Resources>

        <CollectionViewSource x:Key="cvs" />

    </UserControl.Resources>

    2 - Defina o resource como source para o binding do DataGrid e dos controles TextBox.

    <sdk:DataGrid ItemsSource="{Binding}"

                   DataContext="{StaticResource cvs}"

                   AutoGenerateColumns="False">

        <sdk:DataGrid.Columns>

            <sdk:DataGridTextColumn Binding="{Binding Id}"

                                   Header="Id" />

            <sdk:DataGridTextColumn Binding="{Binding Nome}"

                                   Header="Nome" />               

        </sdk:DataGrid.Columns>

    </sdk:DataGrid>

     

    <TextBox Text="{Binding Source={StaticResource cvs}, Path=Id, Mode=TwoWay}" />

    <TextBox Text="{Binding Source={StaticResource cvs}, Path=Nome, Mode=TwoWay}" />

    <TextBox Text="{Binding Source={StaticResource cvs}, Path=Email, Mode=TwoWay}" />

    Obs: Nesse passo, se a sua classe Cliente implementa INotifyPropertyChanged, após o controle TextBox perder o foco o DataGrid é atualizado com o novo valor.

    3 - No code-behind, defina a propriedade Source do CollectionViewSource com a sua coleção de clientes (que provavelmente é a sua classe Clientes).

    // coleção de clientes

    var colecaoDeClientes = new ObservableCollection<Cliente>

    {

        new Cliente { Id = 1, Nome = "Ari", Email = "ari@mail.com" },

        new Cliente { Id = 2, Nome = "Bruno", Email = "bruno@mail.com" },

        new Cliente { Id = 3, Nome = "Regiana", Email = "regiana@mail.com" },

    };

     

    // recupera CollectionViewSource dos resources

    var collectionViewSource = (CollectionViewSource)this.Resources["cvs"];

     

    // define source

    collectionViewSource.Source = colecaoDeClientes;

    Mais detalhes nos links abaixo:

    CollectionViewSource Class
    http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource(v=VS.95).aspx

    How to: Bind to Hierarchical Data and Create a Master/Details View
    http://msdn.microsoft.com/en-us/library/cc645060(v=VS.95).aspx

    Espero ter ajudado.

    Att.

    Ari C. Raimundo
    MCAD, MCTS
    http://araimundo.blogspot.com

    • Sugerido como Resposta Ari C. Raimundo terça-feira, 19 de outubro de 2010 03:08
    • Marcado como Resposta Ari C. Raimundo quarta-feira, 27 de outubro de 2010 11:45
    quinta-feira, 14 de outubro de 2010 02:07

Todas as Respostas

  • Lucas,

    Uma maneira é utilizar a classe CollectionViewSource e então não necessitar do código para tratar o evento SelectionChanged. Para isso, siga os seguintes passos (ou faça algo parecido).

    1 - Defina um resource para a classe CollectionViewSource no XAML.

    <UserControl.Resources>

        <CollectionViewSource x:Key="cvs" />

    </UserControl.Resources>

    2 - Defina o resource como source para o binding do DataGrid e dos controles TextBox.

    <sdk:DataGrid ItemsSource="{Binding}"

                   DataContext="{StaticResource cvs}"

                   AutoGenerateColumns="False">

        <sdk:DataGrid.Columns>

            <sdk:DataGridTextColumn Binding="{Binding Id}"

                                   Header="Id" />

            <sdk:DataGridTextColumn Binding="{Binding Nome}"

                                   Header="Nome" />               

        </sdk:DataGrid.Columns>

    </sdk:DataGrid>

     

    <TextBox Text="{Binding Source={StaticResource cvs}, Path=Id, Mode=TwoWay}" />

    <TextBox Text="{Binding Source={StaticResource cvs}, Path=Nome, Mode=TwoWay}" />

    <TextBox Text="{Binding Source={StaticResource cvs}, Path=Email, Mode=TwoWay}" />

    Obs: Nesse passo, se a sua classe Cliente implementa INotifyPropertyChanged, após o controle TextBox perder o foco o DataGrid é atualizado com o novo valor.

    3 - No code-behind, defina a propriedade Source do CollectionViewSource com a sua coleção de clientes (que provavelmente é a sua classe Clientes).

    // coleção de clientes

    var colecaoDeClientes = new ObservableCollection<Cliente>

    {

        new Cliente { Id = 1, Nome = "Ari", Email = "ari@mail.com" },

        new Cliente { Id = 2, Nome = "Bruno", Email = "bruno@mail.com" },

        new Cliente { Id = 3, Nome = "Regiana", Email = "regiana@mail.com" },

    };

     

    // recupera CollectionViewSource dos resources

    var collectionViewSource = (CollectionViewSource)this.Resources["cvs"];

     

    // define source

    collectionViewSource.Source = colecaoDeClientes;

    Mais detalhes nos links abaixo:

    CollectionViewSource Class
    http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource(v=VS.95).aspx

    How to: Bind to Hierarchical Data and Create a Master/Details View
    http://msdn.microsoft.com/en-us/library/cc645060(v=VS.95).aspx

    Espero ter ajudado.

    Att.

    Ari C. Raimundo
    MCAD, MCTS
    http://araimundo.blogspot.com

    • Sugerido como Resposta Ari C. Raimundo terça-feira, 19 de outubro de 2010 03:08
    • Marcado como Resposta Ari C. Raimundo quarta-feira, 27 de outubro de 2010 11:45
    quinta-feira, 14 de outubro de 2010 02:07
  • Boooaaa Ari.....

    Valeu cara....

    Abs,


    Lucas Giusti
    quinta-feira, 14 de outubro de 2010 02:58
  • Ari,

    No cenário acima.....

    tem como utilizar um CollectionViewSource para o grid...e outro para os campos de detalhe ??

    daí, quando um item do grid é selecionado.....este outro CollectionVewSource (cliente) é preenchido com o SelectedItem do grid......mas quando um campo de detalhe, por exemplo o campo nome for alterado, afetar a segunda CollectionViewSource (cliente) e não a primeira (Clientes "do grid")....

    tem como ?


    Lucas Giusti
    segunda-feira, 18 de outubro de 2010 15:38
  • Olá Lucas,

    Na verdade a sua classe Cliente não é um CollectionViewSource.

    Como eu comentei anteriormente:

    ...se a sua classe Cliente implementa INotifyPropertyChanged , após o controle TextBox perder o foco o DataGrid é atualizado com o novo valor.

    Portanto, se a sua classe Cliente não implementar INotifyPropertyChanged (o que não acho legal) o seu DataGrid não apresentará automaticamente essa alteração. Mesmo assim, o seu CollectionViewSource ainda possui binding com a sua coleção de clientes que foi alterada.

    Uma alternativa seria alterar o modo do binding dos controles TextBox para OneWay (ao invés de TwoWay) e então realizar a alteração do registro corrente em um botão Salvar. Por exemplo, no evento Click desse botão teríamos...

    // recupera CollectionViewSource dos resources

    var collectionViewSource = (CollectionViewSource )this .Resources["cvs" ];

     

    // ICollectionView

    var collectionView = collectionViewSource.View;

     

    // registro corrente

    var cliente = collectionView.CurrentItem as Cliente ;

    if (cliente != null )

    {

        cliente.Nome = this .txtNome.Text;

        cliente.Email = this .txtEmail.Text;

    }

    Espero ter ajudado.

    Att.

    Ari C. Raimundo
    MCAD, MCTS
    http://araimundo.blogspot.com

    terça-feira, 19 de outubro de 2010 03:00
  • Puts...entendi.....

    se eu quero trabalhar com as classes separadamente (separando o Binding) tenho que não utilizar INotifyPropertyChanged, oq também não acho legal....

    ou trabalhar realmente separado atribuindo cada um dos valores (textbox) à classe......

    mas legal....pelo menos deu uma clareada sobre como trabalhar com Binding....

    valeu cara....

    Abs,


    Lucas Giusti
    quarta-feira, 20 de outubro de 2010 01:50