Updating values of an object from a collection via Binding WPF, MVVM

3

Following the MVVM model, I am not able to update the values of a variable of an object in a collection, display them on the screen or the user type and this value is passed to the variable.

In my case, I have a customer registration screen and this client can contain more than one address. Well, a control of type ItemsControl receives in the ItemsSource Binding attribute of the Endereços collection and in the DataTemplate attribute the layout of each ItemControl(endereço) and each field with its Binding .

Follow the codes for a better understanding:

  

ViewModel

public class ClienteViewModel : INotifyPropertyChanged
    {
        public ClienteViewModel()
        {
            Enderecos = new ObservableCollection<EnderecoViewModel>();
        }

        private ObservableCollection<EnderecoViewModel> _enderecos;

        public ObservableCollection<EnderecoViewModel> Enderecos
        {
            get { return _enderecos; }
            set
            {
                _enderecos = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
  

XAML

<ItemsControl ItemsSource="{Binding Path=Enderecos, Mode=TwoWay}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate DataType="{x:Type endereco:EnderecoViewModel}">
                                <TextBlock Text="CEP:"/>
                                <xctk:MaskedTextBox Mask="00000-000" TextChanged="TbCep_OnTextChanged" Text="{Binding Cep}" Tag="{Binding EnderecoId}"/>
                                <TextBlock Text="Logradouro"/>
                                <TextBox Text="{Binding Logradouro}"/>
                                <TextBlock Text="Número:" />
                                <TextBox Text="{Binding Numero}"/>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
  

XAML.cs

private void TbCep_OnTextChanged(object sender, TextChangedEventArgs e)
        {
            var enderecoOnList =
                _clienteViewModel.Enderecos.FirstOrDefault(
                    x =>
                        x.EnderecoId == Guid.Parse(sender.GetType().GetProperty("Tag").GetValue(sender).ToString()));


            var endereco = new Endereco();
            if (enderecoOnList != null && enderecoOnList.Cep != null)
            {
                var cep = enderecoOnList.Cep.Replace("-", "");
                if (cep.Length == 8)
                {
                            endereco = BuscarEnderecoPorCep(cep);
                            if (endereco != null)
                            {
                                enderecoOnList.Logradouro = endereco.Logradouro;
                                enderecoOnList.Complemento = endereco.Complemento;
                                enderecoOnList.Bairro = endereco.Bairro;
                                enderecoOnList.Cidade = endereco.Cidade;
                                enderecoOnList.Estado = endereco.Estado;
                                enderecoOnList.CodigoIbge = endereco.CodigoIbge;
                                enderecoOnList.Pais = "Brasil";
                            }
                }
            }
        }

When this "TbCep_OnTextChanged" event is triggered, the enderecoOnList variable is given the correct position address, but all variables are set to null , including the user-entered ZIP code on the screen.

When I change any variable of an address object via the screen, the Addresses collection does not receive this value in that position or in another position in the collection.

NOTE: I have a add button, which adds a new address object to the Addresses collection, and the Binding normally occurs on the screen. I also have a remove button, which removes an address object from the Addresses collection, which also works perfectly. That is, binding bound to Addresses works, however the Binding bound to a variable of an Address object in the Addresses collection does not work.

How can I solve this problem, I tried to set Binding Mode as TwoWay, but I still did not succeed, or what to fix in my code?

    
asked by anonymous 26.10.2016 / 15:38

1 answer

2

Well folks, I managed to solve this my problem after some more study time. As I mentioned in the question above, the Binding in the Endereços collection worked perfectly, that at the same time in your children endereço will not occur Binding of its variables. Thinking and focusing on this problem, we can note that each endereço child will also need to implement the INotifyPropertyChanged class and call the OnPropertyChanged method that is triggered to update the on-screen property. Where I did not do it before.

Follow the code for class endereço

  

ViewModel

public class CreateClienteEnderecoViewModel : INotifyPropertyChanged
    {
        public CreateClienteEnderecoViewModel()
        {
            EnderecoId = Guid.NewGuid();
        }

        #region Properties
        public Guid EnderecoId { get; set; }

        private string _logradouro;
        public string Logradouro
        {
            get { return _logradouro; }
            set
            {
                _logradouro = value;
                OnPropertyChanged();
            }
        }

        private string _numero;
        public string Numero
        {
            get { return _numero; }
            set
            {
                _numero = value;
                OnPropertyChanged();
            }
        }

        #endregion
        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

I hope to help more people because I have been slow to find a solution to this problem! Thanks!

    
26.10.2016 / 19:42