none
ListBox SelectedItems em WindowsPhone

    Pergunta

  • Estou utilizando MVVM Light Toolkit para o desenvolvimento da minha Aplicação WP7. Estava tudo correndo bem quando me deparei com um probleminha.

    Possuo uma View com uma ListBox que é preenchida com dados de uma disciplina, porém na lista é apenas mostrado o nome da disciplina, e quando eu selecionar alguma disciplina na lista ela vai para uma pagina com os detalhes da disciplina. Até ai tudo bem! Porém não consigo fazer a ligação dos dados da Disciplina selecionada nesta View.

    Tipo: Mostrar o nome da disciplina na AppTitle e os dados na grid dessa página. O que estou fazendo de errado será? 

    domingo, 26 de fevereiro de 2012 16:44

Respostas

  • Olá Weber,

    Legal que está usando o MVVM Light.

    Para passar infos de um ViewModel (lista de disciplinas) para outro ViewModel (detalhes da disciplina) de uma maneira desacoplada, eu sugiro você utilizar o Messager. Vou supor que você possui uma classe chamada "Disciplina".

    No seu ViewModel que lista as disciplinas, coloque  essa linha exatamente antes de navegar para o ViewModel de detalhes:

    Messenger.Default.Send(disciplinaEscolhida);

    Isso irá fazer com que todos os objetos que se inscreveram no tipo de mensagem "Disciplina" recebam essa nova disciplina escolhida. 

    No seu ViewModel de Detalhes, registre-o para receber "mensagens" sobre disciplinas. Coloque no construtor:

    Messenger.Default.Register<Disciplina>(this, DisciplinaEscolhida);

    E crie o método "DisciplinaEscolhida":

    public void DisciplinaEscolhida(Disciplina disciplina) {
       //Atualiza todos os campos que quer mostrar na View
    }

    E pronto!

    Um ViewModel vai enviar uma mensagem (no caso, a disciplina) para outro sem que os dois tenham qualquer referência.

    Espero que ajuda. 

    []'s!


    - André Carlucci - Way2 Technology - twitter/andrecarlucci - andrecarlucci.com

    • Marcado como Resposta Weber D. Amaral sexta-feira, 9 de março de 2012 17:21
    terça-feira, 28 de fevereiro de 2012 12:10
    Moderador

Todas as Respostas

  • Sem ver código será sempre complicado de saber concretamente o que se passa... talvez um exemplo te possa ajudar, como por exemplo este:

    http://geekswithblogs.net/lbugnion/archive/2010/03/16/sample-code-for-my-mix10-talk-online.aspx


    Pedro Lamas
    DevScope | Senior Software Development Engineer & WP7 Development Speaker
    www.pedrolamas.com | @pedrolamas

    segunda-feira, 27 de fevereiro de 2012 11:16
  • Olá Weber,

    Legal que está usando o MVVM Light.

    Para passar infos de um ViewModel (lista de disciplinas) para outro ViewModel (detalhes da disciplina) de uma maneira desacoplada, eu sugiro você utilizar o Messager. Vou supor que você possui uma classe chamada "Disciplina".

    No seu ViewModel que lista as disciplinas, coloque  essa linha exatamente antes de navegar para o ViewModel de detalhes:

    Messenger.Default.Send(disciplinaEscolhida);

    Isso irá fazer com que todos os objetos que se inscreveram no tipo de mensagem "Disciplina" recebam essa nova disciplina escolhida. 

    No seu ViewModel de Detalhes, registre-o para receber "mensagens" sobre disciplinas. Coloque no construtor:

    Messenger.Default.Register<Disciplina>(this, DisciplinaEscolhida);

    E crie o método "DisciplinaEscolhida":

    public void DisciplinaEscolhida(Disciplina disciplina) {
       //Atualiza todos os campos que quer mostrar na View
    }

    E pronto!

    Um ViewModel vai enviar uma mensagem (no caso, a disciplina) para outro sem que os dois tenham qualquer referência.

    Espero que ajuda. 

    []'s!


    - André Carlucci - Way2 Technology - twitter/andrecarlucci - andrecarlucci.com

    • Marcado como Resposta Weber D. Amaral sexta-feira, 9 de março de 2012 17:21
    terça-feira, 28 de fevereiro de 2012 12:10
    Moderador
  • Boa tarde André. 

    Primeiramente, muito obrigado pela sua resposta. O MVVM Light é uma ótima escolha para desenvolver apps. Pois bem, vamos a minha pergunta: _rsrsrs

    Como você me indicou eu usei a Classe Messenger para porém com algumas modificações, que são:

    >> Trecho do XAML da DisciplinaView.xaml

    <ListBox ItemsSource="{Binding MinhasDisciplinas, Mode=OneWay}"
             ItemTemplate="{StaticResource ListBoxItemTemplate}" 
             SelectedItem="{Binding SelectedDisciplina, Mode=TwoWay}"
             Margin="12,24,12,0">
               <ListBox.ItemsPanel>
                 <ItemsPanelTemplate>
                   <toolkit:WrapPanel />
                 </ItemsPanelTemplate>
               </ListBox.ItemsPanel>
               <i:Interaction.Triggers>
                 <i:EventTrigger EventName="SelectionChanged">
                   <ec:NavigateToPageAction TargetPage="/View/DisciplinaDetailView.xaml"/>
                 </i:EventTrigger>
               </i:Interaction.Triggers>
             </ListBox>

    >> Trecho da DisciplinaViewModel.cs

    public Disciplina SelectedDisciplina
            {
                get
                {
                    return _selectedDisciplina;
                }
    
                set
                {
                    if (_selectedDisciplina == value)
                    {
                        return;
                    }
    
                    var oldValue = _selectedDisciplina;
                    _selectedDisciplina = value;
                    
                    RaisePropertyChanged<Disciplina>(SelectedDisciplinaPropertyName, oldValue, value, true);
                }
            }

    >> Trecho DisciplinaDetailViewModel.cs [Propriedade de ligação]

    public Disciplina SelectedDisciplina
            {
                get
                {
                    return _selectedDisciplina;
                }
    
                set
                {
                    if (_selectedDisciplina == value)
                    {
                        return;
                    }
    
                    _selectedDisciplina = value;
                    RaisePropertyChanged(SelectedDisciplinaPropertyName);
                }
            }

    >> Trecho Classe DisciplinaDetailViewModel.cs [Construtor]

    public DisciplinaDetailViewModel()
            {
                if (IsInDesignMode)
                {
                    // Blender mode
                }
                else
                {          MessengerInstance.Register<PropertyChangedMessage<Disciplina>>(this, (action) =>
                        {
                            DispatcherHelper.CheckBeginInvokeOnUI(() =>
                                {
                                    SelectedDisciplina = action.NewValue;
                                });
                        });
                }
            }

    Bom, ao chegar na View [Tela] DisciplinaView, OK, é mostrado todas as disciplina tudo certinho. Mas quando seleciono uma disciplina no minha lista e navego para a tela [DisciplinaDetailView], acontece uma coisa diferente do que eu esperava:

    Na primeira vez que seleciono a disciplina as informações não são mostradas nessa tela [DisciplinaDetailView], mas se eu voltar para a [DisciplinaView] e selecionar novamente, a mesma ou qualquer outra disciplina nessa lista, ai sim as informações são passadas para essa nova view. Detalhes:

    - Com ou sem a DispatcherHelper.CheckBeginInvokeOnUI() o mesmo problema ocorre. E já implementei a DispatcherHelper.Initialize() no Construtor do App() [App.xaml.cs].

    AO debugar o código me parece que o argumento passado para o parametro ACTION não tem absolutamente nada! Ou seja, a minha propriedade SelectedDisciplina fica sem valor na primeira vez. MAs depois, como informei ocorre como esperado.

    Alguem poderia me ajuda nesse problema?? 

    Att.

    Weber Amaral

    quarta-feira, 29 de fevereiro de 2012 16:08
  • Olá Weber,

    O que eu acho que pode estar acontecendo é um problema de concorrência. A navegação está acontecendo antes da mensagem chegar no ViewModel e este não está carregando os novos valores. Tente uma dessas 2 coisas:

    Retire isto do seu ViewModel de detalhes:

    if (_selectedDisciplina == value) {
         return;
    }

    Ou, faça a mensagem chegar antes:

    Modifique seu EventTrigger para chamar um método no ViewModel ao invés de navegar diretamente. Nesse método, dispare a mensagem utilizando o Messenger e só depois navegue para a página de detalhes.

    []'s!


    - André Carlucci - Way2 Technology - twitter/andrecarlucci - andrecarlucci.com

    quinta-feira, 1 de março de 2012 18:25
    Moderador
  • Fala ae André. Tudo certinho?

    Cara então, era esse mesmo o problema, minha navegação acontecia antes da mensagem ser enviada para minha ViewModel, por isso não carregava os valores da primeira vez.

    Então. Tirei horas para pesquisa aqui e até que uma luz e solução surgiu, claro que tudo isso depois de uma dica de uma amigo.
    Eu alterei a minha ViewModeLocator.cs. Andei dando uma olhada como era implementada na versão 3 e as modificações feitas na versão 4, versão do MVVM Light Toolkit.

    Bom, agora vamos a solução.

    No construtor estático da ViewModelLocator como de costume você registra suas ViewModel´s, como no exemplo:

    SimpleIoc.Default.Register<ViewModel>();

    e instancia na Propriedade:

    public ViewModel ViewModel
            {
                get
                {
                    return ServiceLocator.Current.GetInstance<ViewModel>();
                }
            }

    O que eu fiz, registrei minha DisciplinaDetailViewModel no construtor estático como de costume, e instanciei em um construtor não-estático da ViewModelLocator, como era feita na versão anterior do MVVM Light, desse modo:

    public ViewModelLocator()
            {
                ServiceLocator.Current.GetInstance<DisciplinaDetailViewModel>();
            }

    Dessa forma minha ViewModel já está instanciada e com a mensagem registrada. Assim quando faço a navegação para essa tela as informações são passadas corretamente.

    Não sei se é a forma mais correta, mas não muda muito do que era feita na v3 do MVVM Light. Mas estou aberto a sugestões;

    André valeu pela ajuda!

    quinta-feira, 1 de março de 2012 22:49
  • Olá Weber,

    Registrar no ViewModelLocator é o caminho sim. Um dos pontos de minha palestra no Teched foi justamente isso, facilita muito!

    Fico feliz que deu certo, poderia por favor marcar como resposta o post que mais te ajudou?

    []'s e qualquer coisa é só postar aqui no forum.



    - André Carlucci - Way2 Technology - twitter/andrecarlucci - andrecarlucci.com

    segunda-feira, 5 de março de 2012 14:02
    Moderador