Search code examples
c#wpfmvvmcomboboxselectedvalue

Getting the selected value from a combobox populated from a data base, for comparison, through data binding WPF/ MVVM


I am a beginner in C#; the project is made in Visual Studio (wpf) using entity framework and view models. I have populated a combobox with only the name of 'Employees' from my database. What I want to do is get the selected item value in a variable(or directly compare it to the name stored in the database, to take all the other table columns associated with that name; in my case i have age,attributes..etc)

If i go directly into the MainWindow.xaml.cs, i can easily use

Object selectedItem = ComboBoxName.SelectedItem; and it gets the job done. However, I need to implement this in my MainWindowsViewModel.cs. I've found out about SelectedItem="{Binding ..., Mode=...}" and tried several solutions, but I can't find any to work.

My combobox in the XAML:

 <ComboBox x:Name="comboPersonal" Grid.Column="6" HorizontalAlignment="Left" Margin="13,60,-62,0" Grid.Row="1" VerticalAlignment="Top" Width="183" ItemsSource="{Binding ang1}" SelectedItem="{Binding Path=Employers, Mode=TwoWay}"  />

The combobox is populated through this:

 public IList<string> ang1
        {
            get
            {
                using (ProbaHotel_1Entities db = new ProbaHotel_1Entities())
                {
                    var employee = db.Personal.Select(ang => ang.Nume).ToList();



                    return employee.ToList();
                }
            }
        }

In my MainWindowViewModel(which is mostly wrong):

 public IList<string> Employers
        {
            get
            {
                using (ProbaHotel_1Entities db = new ProbaHotel_1Entities())
                {
                    var vNume = db.Personal.Select(ang => ang.Nume);
                    this.NumeText = vNume.ToString();

                }
                return this.Employers;
            }

            set { }
        }

NumeText is the variable a textbox is binded to. When I select an item from the ComboBox, I wanted that value to be trasmitted to the textbox. The Select statement misses the WHERE to compare the selected value to the names in the database

Text box XAML:

<TextBox x:Name="text_nume" HorizontalAlignment="Left" Height="23"  TextWrapping="Wrap" Text="{Binding NumeText}" VerticalAlignment="Top" Width="89" Grid.Column="1" Grid.Row="0" />

In my MainWindowViewModel:

private string numeText;
        public string NumeText
        {
            get
            {
                return this.numeText;
            }
            set
            {

                this.numeText = value;
            }
        }

Solution

  • You can use List which contains model and bind to combobox itemsource and you can bind DisplayMemberPath to say "Name" which is the property of model and bind SelectedItem to this model .

    Please see the code . I have used dummy string values. In your case this should be populated from DB as you mentioned . Note that, in the setter of SelectedEmployee i am assigning value to NumText as per your requirement . As soon as selected item changes, this will be assigned and shown in XAML textbox

    In your case, you have wrongly assigned SelectedItem to list . it should be related to itemsource which you have bound . You created separate lists one for itemsource and one for selected item. And also i cannot see any changes in property setters related to INotifyPropertyChanged in your code .

    XAML :

    <Window x:Class="WpfApplication13.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApplication13"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="50*"/>
                <RowDefinition Height="50*"/>
            </Grid.RowDefinitions>
            <TextBox x:Name="text_nume" HorizontalAlignment="Center" Height="23"  TextWrapping="Wrap" Text="{Binding NumeText}" VerticalAlignment="Center" Width="89" Grid.Row="0" />
            <ComboBox x:Name="comboPersonal" Grid.Row="1" Height="30" Width="100" HorizontalAlignment="Center" DisplayMemberPath="Name" VerticalAlignment="Center" Margin="13,60,-62,0"  ItemsSource="{Binding Ang1}" SelectedItem="{Binding SelectedEmployee}"  />
        </Grid>
    </Window>
    

    ViewModel:

     public class ViewModel : INotifyPropertyChanged
        {
    
            #region Constants and Enums
    
            #endregion
    
            #region Private and Protected Member Variables 
            private IList<EmployeeModel> ang1;
            EmployeeModel _selectedEmployee;
            private string numeText;
            #endregion
    
            #region Private and Protected Methods
            private void OnPropertyChanged(string propName)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
            }
            #endregion
    
            #region Constructors
            public ViewModel()
            {
                Ang1 = new List<EmployeeModel>();
                Ang1.Add(new EmployeeModel() {  Name="1"});
                Ang1.Add(new EmployeeModel() { Name = "2" });
            }
            #endregion
    
            #region Public Properties
            public IList<EmployeeModel> Ang1
            {
                get
                {
                    return ang1;
                }
                set
                {
                    ang1 = value;
                    OnPropertyChanged(nameof(Ang1));
                }
            }
    
            public EmployeeModel SelectedEmployee
            {
                get
                {
                    return _selectedEmployee;
                }
                set
                {
                    _selectedEmployee = value;
                    NumeText = value.Name;
                    OnPropertyChanged(nameof(SelectedEmployee));
                }
            }
    
            public string NumeText
            {
                get
                {
                    return this.numeText;
                }
                set
                {
    
                    this.numeText = value;
                    OnPropertyChanged(nameof(NumeText));
                }
            }
            #endregion
    
            #region Public Methods
            public event PropertyChangedEventHandler PropertyChanged;
    
            #endregion
    
    
        }
    

    Model:

     public class EmployeeModel
        {
            public string Name { get; set; }
        }
    

    I used INotifyPropertyChanged for binding notification . Let me know if this helps