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;
}
}
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