简体   繁体   中英

Update combobox MVVM (XAML & C#)

I have a form with 2 combos, among other fields. 1 combo is filled with brand names ( cmbMarca ). This combo is filled correctly. The other combo ( cmbModelo ) should be filled with models of the selected brand.

My problem is that the combo with models ( cmbModelo ) is not updated when selecting a brand (cmbBrand). When I select a brand, runs all the code but does not display any item in the combo " cmbModelo "

FillingForm.xaml

    <Input:SfComboBox x:Name="cmbMarca"   x:uid="BrandsCombo"
    DisplayMemberPath="marca"
ItemsSource="{Binding MarcasSAT.Marcas}"                                                       SelectedValue="{Binding marca, Mode=TwoWay}"
    SelectedValuePath="marca"     
    Tag="{Binding Path=SelectedMarca, Mode=TwoWay}"                                                     SelectionChanged="cmbMarca_SelectionChanged"/>  

    <Input:SfComboBox x:Name="cmbModelo"    x:uid="ModelosCombo" 
    DisplayMemberPath="modelo"    
    ItemsSource="{Binding ModelosSAT.Modelos}" 
     SelectedValue="{Binding modelo, Mode=TwoWay}"
    SelectedValuePath="modelo" />

FillingForm.CS

  private void cmbMarca_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {            
                MarcaViewModel curItem = (MarcaViewModel)cmbMarca.SelectedItem;               
                this.cmbMarca.Tag  = curItem.idMarca;
        } 

FillingViewModel.cs

public class FillingViewModel : ViewModelBase
{

        private readonly MarcasViewModel marcasSAT = new MarcasViewModel();
        public MarcasViewModel MarcasSAT
        {
            get { return this.marcasSAT; }
        }

        private ModelosViewModel modelosSAT = new ModelosViewModel();
        public ModelosViewModel ModelosSAT
        {
            get
            {
                return this.modelosSAT;
            }
            set
            {
                modelosSAT = value;
                RaisePropertyChanged("ModelosSAT");
            }
        }

        private int _selectedMarca;
        public int SelectedMarca
        {
            get { return _selectedMarca; }
            set 
            {
                _selectedMarca = value;
                RaisePropertyChanged("SelectedMarca");
                modelosSAT.MarcaID = _selectedMarca;           
            }
        }

}

ModelosViewModel.cs

 public class ModelosViewModel : ViewModelBase
    {
        private ObservableCollection<ModeloViewModel> modelos;
        public ObservableCollection<ModeloViewModel> Modelos
        {
            get
            {
                return modelos ;
            }
            set
            {
                modelos  = value;
                RaisePropertyChanged("Modelos");
            }
        }

        public ObservableCollection<ModeloViewModel> GetModelos()
        {
            modelos  = new ObservableCollection<ModeloViewModel>();
            using (var db = new SQLite.SQLiteConnection(App.DBPath))
            {
                var query = db.Table<Modelos>().Where(c => c.idMarca == _marcaID);   
                //var query = db.Table<Modelos>();   
                foreach (var _mrc in query)
                {
                    var mrc = new ModeloViewModel()
                    {
                        idMarca  = _mrc.idMarca,
                        idModelo = _mrc.idModelo,
                        modelo   = _mrc.modelo                          
                    };
                    modelos.Add(mrc);
                }
            }
            return modelos ;
        }

        private int _marcaID=0;
        public int MarcaID
        {
            get {
                return _marcaID; 
            }
            set
            {
                _marcaID = value;
                RaisePropertyChanged("MarcaID");
                this.GetModelos();
            }
        }

        //public ModelosViewModel()
        //{           
        //    this.modelos = GetModelos();
        //}

    }

MarcasViewModel.cs

 public class MarcasViewModel : ViewModelBase
    {
        private ObservableCollection<MarcaViewModel> marcas;
        public ObservableCollection<MarcaViewModel> Marcas
        {
            get
            {
                return marcas ;
            }

            set
            {
                marcas  = value;
                RaisePropertyChanged("Marcas");
            }
        }


        public ObservableCollection<MarcaViewModel> GetMarcas()
        {
            marcas = new ObservableCollection<MarcaViewModel>();
            using (var db = new SQLite.SQLiteConnection(App.DBPath))
            {
                var query = db.Table<Marcas>();
                foreach (var _mrc in query)
                {
                    var mrc = new MarcaViewModel()
                    {
                        idMarca  = _mrc.idMarca ,
                        marca  = _mrc.marca                         
                    };
                    marcas.Add(mrc);
                }
            }
            return marcas ;
        }

        public MarcasViewModel()
        {
            this.marcas = GetMarcas();
        }

    }

ViewModelBase.cs

 public class ViewModelBase
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void RaisePropertyChanged(string propertyName)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    }

UPDATE1:

when I select a brand item, only the next code is called and in this order:

1st (in FillinfgForm.cs)

 private void cmbMarca_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {            
                MarcaViewModel curItem = (MarcaViewModel)cmbMarca.SelectedItem;        
                this.cmbMarca.Tag  = curItem.idMarca;            
        }  

2nd (in FillingViewModel.cs)

public int SelectedMarca 
  set 
            {
                _selectedMarca = value;
                RaisePropertyChanged("SelectedMarca");
                modelosSAT.MarcaID = _selectedMarca;           
            }

3rd (in ModelosViewModel.cs)

Public int MarcaID
    {            
        set
        {
            _marcaID = value;
            RaisePropertyChanged("MarcaID");
            this.GetModelos();
        }
    }

4th

public ObservableCollection<ModeloViewModel> GetModelos()
    {
        modelos  = new ObservableCollection<ModeloViewModel>();
        using (var db = new SQLite.SQLiteConnection(App.DBPath))
        {
            var query = db.Table<Modelos>().Where(c => c.idMarca == _marcaID);   
            //var query = db.Table<Modelos>();   
            foreach (var _mrc in query)
            {
                var mrc = new ModeloViewModel()
                {
                    idMarca  = _mrc.idMarca,
                    idModelo = _mrc.idModelo,
                    modelo   = _mrc.modelo                          
                };
                modelos.Add(mrc);
            }
        }
        return modelos ;
    }

The problem is in GetMarcas() methods. As you can see you work not with the property but with the field - 'marcas'. But when you assign a value to a field (in you particular case marcas = new ObservableCollection();) PropertyChanged method is not invoked. That is why you don't see UI changes. You should work with the property istead of field or you can clear the existing ObservableCollection and add you values. Both variants should work. So the following code should work:

public ObservableCollection<MarcaViewModel> GetMarcas()
{
    Marcas = new ObservableCollection<MarcaViewModel>();
    using (var db = new SQLite.SQLiteConnection(App.DBPath))
    {
        var query = db.Table<Marcas>();
        foreach (var _mrc in query)
        {
            var mrc = new MarcaViewModel()
            {
                idMarca  = _mrc.idMarca ,
                marca  = _mrc.marca                         
            };
            marcas.Add(mrc);
        }
    }
    return marcas ;
}

or, a better solution:

public ObservableCollection<MarcaViewModel> GetMarcas()
{
    Marcas.Clear();
    using (var db = new SQLite.SQLiteConnection(App.DBPath))
    {
        var query = db.Table<Marcas>();
        foreach (var _mrc in query)
        {
            var mrc = new MarcaViewModel()
            {
                idMarca  = _mrc.idMarca ,
                marca  = _mrc.marca                         
            };
            Marcas.Add(mrc);
        }
    }
    return marcas;
}

Also there is a good practice called "do not ignore return values", as you can see you don't need to return ObservableCollection from GetMarcas , so either rewrite it so that it returns nothing or rewrite invoking code (it dependes on your existing code).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM