Bind an ObservableCollection to a ComboBox in WPF - c#

I'm using Entity Framework as my database source and need to convert a Linq query "var" type to an ObservableCollection. I then need to bind the ObservableCollection to a ComboBox on WPF form; binding to ItemsSource, DisplayMemeberPath, SelectedValuePath and SelectedValue.
Here is Code:
using (PulseContext pc = new PulseContext())
{
var maritalcodes = from m in pc.CodeMaster
where m.Type == "16"
select new { m.Code, m.Description };
prop.ClientData.Options = new ObservableCollection<object>(maritalcodes);
}
Problem is the ComboBox is showing this as "{ Code = ????, Description = ???? }" instead of bind to code for value and description for display. What do I have to do to get the ComboBox to bind to the individual elements?

You need to set SelectedValuePath and DisplayMemberPath like this:
prop.ClientData.Options = new ObservableCollection<object>(maritalcodes);
prop.ClientData.Options.SelectedValuePath = "Code";
prop.ClientData.Options.DisplayMemberPath = "Description";
Or you can set them in xaml like this:
<ComboBox ItemsSource="{Binding Path=maritalcodes}"
SelectedValuePath="Code"
DisplayMemberPath="Description" />

<ComboBox ItemsSource="{Binding Path=maritalcodes}"
SelectedValuePath="Code"
DisplayMemberPath="Description"
SelectedValue="{Binding Path=Code}"/>
I hope this will help.

Related

WPF Binding DataGridComboBoxColumn to SelectedItem of a ComboBox

I am building an app in WPF (MVVM).
The user is to make a selection in a ComboBox, and the choice is supposed to filter the results available in a DataGridComboBoxColumn (DGCBC) in a DataGrid.
But I am at a loss at how to bind the ComboBox SelectedItem to the DGCBC. I did manage to have the ComboBox filter the results of a second ComboBox, but that logic does not seem to transfer well to the DGCBC.
What I have tried:
My ComboBox:
<ComboBox
DisplayMemberPath="PropertyName1"
ItemsSource="{Binding Collection1}"
Loaded="{s:Action NameOfMethodToPopulateComboBox}"
SelectedItem="{Binding PropertyHolder, UpdateSourceTrigger=PropertyChanged}"/>
The PropertyHolder is ran when an item is selected in the ComboBox, and if it's not null, it runs the method that adds to the ObservableCollection which is bound to the DGCBC. It looks like this:
private ClassName _currentSelectedItem;
public ClassName CurrentSelectedItem {
get { return this,._selectedItem; }
set { SetAndNotify(ref this._selectedItem, value);
if (value != null) {
FillDataGridComboBoxColumn();
}
}
}
The method, FillDataGridComboBoxColumn() looks like this (abbreviated):
DataSet ds = new();
// Code to run stored procedure
// CurrentSelectedItem is given as parameter value
DataTable dt = new();
dt = ds.Tables[0];
MyObservableCollection.Clear();
for (int i = 0; i < dt.Rows.Count; i++) {
DataRow dr = dt.NewRow();
dr = dt.Rows[i];
HolderClass holderClass = new(); // this is the class that is bound to the observablecollection
holderClass.PropertyName = dr["PropertyName2"].ToString();
MyObservableCollection.Add(holderClass);
This is the XAML for the DataGrid and the DataGridComboBoxColumn:
<DataGrid
AutoGenerateColumns="False"
ItemsSource="{Binding MyObservableCollection}">
<DataGridComboBoxColumn
SelectedValueBinding="{Binding PropertyName2, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="PropertyName2"
DisplayMemberPath="PropertyName2"
ItemsSource="{Binding MyObservableCollection}">
/>
</DataGrid>
When I debug, the DataGridComboBoxColumn is able to get the correct number of rows - but they're just empty placeholders; blanks. If I put a break-point in the code, I see that the collection is indeed loaded with the correct values, but they're just not showing.
I am guessing I am doing something wrong with the binding for the DGCBC.
Thank you.
The DataGridComboBoxColumn ItemSource had to be set as a Static Resource:
<Window.Resources>
<CollectionViewSource x:Key="MyObservableCollection" Source="{Binding MyObservableCollection}"/>
</Window.Resources>
And then, in the XAML for the DataGridComboBoxColumn:
<DataGridComboBoxColumn
ItemsSource="{Binding Source={StaticResource MyObservableCollection}}"
DisplayMemberPath="Property2">
</DataGridComboBoxColumn>

WPF binding 2 properties from 1 List

So what i am trying to accomplish is that i am trying to bind 2 properties from 1 list to 2 different ComboBoxes.
code:
combobox1.DataContext = class.repository;
combobox2.DataContext = class.repository;
and in xaml
<ComboBox x:Name="combobox1" ItemsSource="{Binding Name}"/>
<ComboBox x:Name="combobox2" ItemsSource="{Binding Password}"/>
example - repository[0] = "NAME1"
The result i get is when i open ComboBox looks like:
1 item - N
2 item - A
3 item - M
and so on..
and result i want is
1 item = NAME1
2 item = NAME2
...
Thanks for replies.
If repository is a string[], you should bind the ItemsSource to the DataContext itself:
<ComboBox x:Name="combobox1" ItemsSource="{Binding}"/>
If repository is an IEnumerable<YourClass> where YourClass is a type with a Name and a Password property, you should also set the DisplayMemberPath property:
<ComboBox x:Name="combobox1" ItemsSource="{Binding}" DisplayMemberPath="Name" />
<ComboBox x:Name="combobox2" ItemsSource="{Binding}" DisplayMemberPath="Password"/>
You should use DisplayMemberPath property of the ComboBox to specify you want to see the value of propery "Name".

Bind multiple dropdowns from a single list

In MVC, I have a List<CityModel> which contains CityID, City, StateID, State, CountryID, Country. By using the below code I'm able to get the list of cites:
IEnumerable<SelectListItem> objCityList;
IEnumerable<SelectListItem> objStateList;
IEnumerable<SelectListItem> objCountryList;
using (CityModel objCityModel = new CityModel())
{
List<CityModel> cityList = objCityModel.getCityList();
objCityList = cityList.AsEnumerable().Select(m => new SelectListItem() {
Text = m.City,
Value = Convert.ToString(m.CityID)
});
}
How can I bind distinct State and Country from cityList?
From what I understand, you want to extract the State and Country lists from the City list. To do that, you can use something like this
objStateList = cityList.GroupBy(item => item.StateID, (key, items) => new SelectListItem
{
Text = items.First().State,
Value = Convert.ToString(key)
});
objCountryList = cityList.GroupBy(item => item.CountryID, (key, items) => new SelectListItem
{
Text = items.First().Country,
Value = Convert.ToString(key)
});
You just need to use the one list, but change the which property is displayed in the combobox. The selected item is of the same type as the objects on the list.
In your view model just expose the CityList property and then bind the comboboxes ItemsSource to that property.
You can do all this in XAML for instance, like this:
<ComboBox ItemsSource="{Binding CityList}"
DisplayMemberPath="City"
SelectedItem={Binding SelectedCity, Mode=TwoWay>
</ComboBox>
<ComboBox ItemsSource="{Binding CityList}"
DisplayMemberPath="County"
SelectedItem={Binding SelectedCounty, Mode=TwoWay>
</ComboBox>
<ComboBox ItemsSource="{Binding CityList}"
DisplayMemberPath="State"
SelectedItem={Binding SelectedState, Mode=TwoWay>
</ComboBox>

How to change ComboBox.SelectedItem on changing ItemsSource?

I have a ComboBox
<ComboBox ItemsSource="{Binding ElementName=listBox, Path=SelectedItem.Values}" SelectedItem="{Binding Path=SelectedValue}"/>
On changing ItemsSource I can get an error in SelectedItem, because there is no SelectedItem in new ItemsSource. I am need to change SelectedIndex to 0 on ItemsSource changing.
How to do it?
What if before changing the ItemsSource you set it's selected index to -1 and then set the source.
combo.SelectedIndex = -1;
combo.ItemsSource = list;

Gets value from combobox in wpf binding by entity framework

I bind my combobox from entityframework and when I try to get value from my combobox by selecting value it gives back text like this {NameOfCompany = Name } How can i get only the value Name?
Thats the code in xaml
<ComboBox SelectionChanged="ComboFirma_SelectionChanged" Name="ComboFirma" Margin="109,10,10,0" Height="28" VerticalAlignment="Top">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Name="txbCombo" Text="{Binding NameOfCompany}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
And I bind it like this.
var query2 = from f in model.Firmas
select new
{
f.NameOfCompany
};
ComboFirma.ItemsSource = query2.ToList();
I tried something like this to gets the selected value but always i get an exception.
var str = (TextBox)ComboFirma.Template.FindName("txbCombo", ComboFirma);
lblCompanyNameShow.Content = str.SelectedText;
ComboBox.SelectedItem will be of a item type. So normally you would need to cast SelectedItem to type of item in your collection. Now, because, in your case it's anonymous type, it's more difficult I think easiest way to get NameOfCompany is to use dynamic
dynamic selectedItem = ComboFirma.SelectedItem;
var name = selectedItem.NameOfCompany;
or you can use SelectedValue/SelectedValuePath
<ComboBox Name="ComboFirma" ... SelectedValuePath="NameOfCompany">
and in code
var name = (string)ComboFirma.SelectedValue;
Try like this
TextBlock tb1 = (TextBlock)ComboFirma.SelectedItem;
lblCompanyNameShow.Content = str.SelectedText;

Categories

Resources