Bind multiple dropdowns from a single list - c#

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>

Related

How to connect a WPF Combobox to KeyValue-Dictionary

I'm struggeling with a WPF Combobox.
My job is to let the user select an entry, that should be stored in a variable and additionally it is possible, that this variable is changed programatically, so the combobox should selct the corresponding item.
First my code:
public KeyValuePair<string, string> SelectedLanguage { get; set; } //the selected item
public Dictionary<string, string> Languages { get; set; } //the list of combobox items
private void loadLanguages(List<string> languages)
{
Languages = new Dictionary<string, string>();
foreach(string language in languages)
{
//set initial selected item
if(language=="de_DE") SelectedLanguage = new KeyValuePair<string, string>(language, getLanguageDescription(language));
Languages.Add(language, getLanguageDescription(language));
}
}
private string getLanguageDescription(string language)
{
switch (language)
{
case "de_DE_Match":
return "Deutsch";
case "fr_FR_Match":
return "Französisch (Frankreich)";
case "nl_NL_Match":
return "Niederländisch";
case "en_EN_Match":
return "Englisch (GB)";
default:
return "unbekannt";
}
}
And this is my WPF:
<ComboBox x:Name="cbLanguages"
ItemsSource ="{Binding Languages}"
DisplayMemberPath="Value"
SelectedValuePath="Key"
SelectedValue="{Binding SelectedLanguage}" />
<TextBox Text="{Binding SelectedLanguage.Value, Mode=OneWay}"/>
Now the List is shown as expected but there is no item selected, inside the textbox, the SelectedLanguage is shown correctly but not changed if selection of the combobox changes.
So how can I programmatically change the selected item and how can I show the selected item in the textbox? Shouldn't it be enough, if I change the SelectedLanguage?
ItemsSource ="{Binding Languages}"
ok, so you have a combo box that contains a collection of KeyValuePairs, since Languages is a dictionary.
DisplayMemberPath="Value"
This says that the text displayed for each item will be the Value of the KeyValuePair, (the language description)
SelectedValuePath="Key"
This says that when selecting items with SelectedValue, we should be comparing against the Key of the KeyValuePair. (the language code)
SelectedValue="{Binding SelectedLanguage}" />
This binds the selection to SelectedLanguage, which should be a language code (string) as we just specified. However, SelectedLanguage is not a string, but a KeyValuePair. Since your ItemsSource is already a collection of KeyValuePairs, you don't need to worry about SelectedValuePath and SelectedValue at all, you can just use SelectedItem.
<ComboBox x:Name="cbLanguages"
ItemsSource ="{Binding Languages}"
SelectedItem="{Binding SelectedLanguage}"
DisplayMemberPath="Value" />

C# change the selected index of a ComboBox item using LINQ

Im not sure if the title represent the problem I have. The explanation here below should be clearer.
I cannot get my code to select the correct value in the ComboBox with the data from my List. I checked for similar problems here in SO but after reading several I cannot find one that matches my problem.
I fill the list with the follwing code:
if (roleComboBox.SelectionBoxItem.Equals("Player"))
{
memberID++;
Player player = new Player(memberID, team, firstName, lastName, age, salary, yearsActive, position, minutesPerGame);
players.Add(player);
PrintList();
}
Now I want to retrieve the data from the List and put it back into the TextBox/ComboBox it came from so I can change the data and put it back into the List (kinda a modify option). I have a different ComboBox with where I select an ID which matches a memberID which in its turn retrieves the data from the List. I use the following code for that:
private void ModifyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int modifyID = int.Parse(modifyComboBox.SelectedItem.ToString());
var player = players.Where(p => p.memberID == modifyID);
teamComboBox.SelectedValue = player.Select(p => p.team).FirstOrDefault(); // this isnt working as intended
firstNameTextBox.Text = player.Select(p => p.firstName).FirstOrDefault();
lastNameTextBox.Text = player.Select(p => p.lastName).FirstOrDefault();
ageTextBox.Text = player.Select(p => p.age.ToString()).FirstOrDefault();
salaryTextBox.Text = player.Select(p => p.salary.ToString()).FirstOrDefault();
yearsActiveTextBox.Text = player.Select(p => p.yearsActive.ToString()).FirstOrDefault();
minutesPerGameTextBox.Text = player.Select(p => p.minutesPerGame.ToString()).FirstOrDefault();
}
While the TextBoxes get filled with the correct data the ComboBox just gets blank.
This is de XAML code for the ComboBox if needed:
<ComboBox x:Name="teamComboBox" HorizontalAlignment="Left" Margin="200,38,0,0" VerticalAlignment="Top" Width="220">
<ComboBoxItem IsSelected="True">-Choose a team-</ComboBoxItem>
<ComboBoxItem>Minnesota Timberwolves</ComboBoxItem>
<ComboBoxItem>Charlotte Hornets</ComboBoxItem>
<ComboBoxItem>LA Lakers</ComboBoxItem>
</ComboBox>
In this case, the type of SelectedValue needs is ComboBoxItem instead of the string type you passed. If you want to set the SelectedValue programmatically, you can set the SelectedValuePath of teamComboBox as "Content" first, it means to set/get the Content of the ComboBoxItem(ie the string you set for the ComboBoxItem). Then you can set your p.team to SelectedValue. For example:
.xaml:
<ComboBox x:Name="teamComboBox" HorizontalAlignment="Left" SelectedValuePath="Content" Margin="200,38,0,0" VerticalAlignment="Top" Width="220">
<ComboBoxItem IsSelected="True">-Choose a team-</ComboBoxItem>
<ComboBoxItem>Minnesota Timberwolves</ComboBoxItem>
<ComboBoxItem>Charlotte Hornets</ComboBoxItem>
<ComboBoxItem>LA Lakers</ComboBoxItem>
</ComboBox>

Select ComboBoxItem based on its tag value

My ComboBoxItems have string values that represent the name of the item to be selected, but I've stored the value for that item in Tag property of the ComboBoxItem. I use the Tag as the asp.net equivalent to the dropdownlist Item Value.
In the code behind where I set the datagrid template column, I set the ComboBoxItem as follows:
<ComboBoxItem Tag='" + product.ProductGuid + "' Content='" + product.Name + "'></ComboBoxItem>
I need to programmatically select a ComboBoxItem based on the Tag value not the content. In the code below, currentProduct holds the ProductGuid value that I need to select, but this code will select the ComboBoxItem whose Content is my currentProduct
((ComboBox)QuotationDG.Columns[0].GetCellContent(MyData[MyData.Count - 1])).SelectedValue = currentProduct;
Is there a way to set the ComboBox Selected value to the ComboBoxItem whose Tag value is currentProduct?
EDIT:
Here's the code I use to bind my ComboBox Column:
private string CreateDDLColumnEditTemplate(int index, string propertyName, List<Product> ProductList)
{
StringBuilder CellTemp = new StringBuilder();
CellTemp.Append("<DataTemplate ");
CellTemp.Append("xmlns='http://schemas.microsoft.com/winfx/");
CellTemp.Append("2006/xaml/presentation' ");
CellTemp.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>");
CellTemp.Append(String.Format("<ComboBox SelectedValue='{{Binding [{0}], Mode=TwoWay}}'>",0));
foreach (Product product in ProductList)
{
CellTemp.Append("<ComboBoxItem Tag='"+product.ProductGuid+"' Content='" + product.Name + "'></ComboBoxItem>");
}
CellTemp.Append(String.Format("</ComboBox>"));
CellTemp.Append("</DataTemplate>");
return CellTemp.ToString();
}
What you need is
YourComboBox.SelectedValue = currentProduct
and
<ComboBox SelectedValuePath="Tag" etc. etc. etc. />
which means your SelectedValue gets its value from your Tag
The use of the combobox has the ability bind to objects and specify what is to be displayed in the dropdown. Why not use the Product object which you are loading into the tag but show something different on the drop down?
If need be create an extended, Partial object, to display something wholly different in the drop down, but still access the Product item to change the selection.
The suggestion here is to simply bind the combobox to the Product data item. Then you can change the value dynamically without using the Tag property.
For example I have this data type similar to your Product type:
public class PriceItem
{
public string Name { get; set; }
public int Price { get; set; }
}
and here is the data list of values which is saved on my VM as Items.
Items = new List<PriceItem>()
{
new PriceItem() { Name = "Alpha", Price=100 },
new PriceItem() { Name = "Beta", Price=200 },
};
Scenario
Two combo boxes, both bound to the Items data. One combo box shows the Name in its dropdown while the other shows the Price. The Name combobox controls the price combo box, when it changes the price changes as well.
<ComboBox x:Name="comboName" ItemsSource="{Binding Items}" DisplayMemberPath="Name" />
<ComboBox x:Name="comboValue"
ItemsSource="{Binding Items}"
DisplayMemberPath="Price"
SelectedValuePath="Price"
SelectedValue="{Binding SelectedItem.Price, ElementName=comboName, Mode=OneWay}" />
In action both combo boxes are blank. But whenever I select the first one it changes the second. All using the same data/data objects.

Bind an ObservableCollection to a ComboBox in WPF

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.

How to set value of WPF ComboBox Item from C# Code

I am populating my WPF ComboBox like this
foreach (Function fx in XEGFunctions.GetAll())
{
ComboBoxItem item = new ComboBoxItem();
item.Content = fx.Name;
item.ToolTip = fx.Signature;
//item.( some property ) = fx.FunctionValue;
cmbBoxTransformation.Items.Add(item);
}
cmbBoxTransformation.SelectedIndex = 0;
How can I set some different value to each ComboBoxItem.
If the value you're looking to set is only used in the back end, and not displayed to the user, the Tag property is probably your best bet.
item.Tag = fx.FunctionValue;
Two options
You can create derived type from ComboBoxItem, and define properties in derived type.
You can create arbitrary collection of item (with your custom properties), and set ComboBox.ItemsSource to that collection, and DisplayMemberPath to the field that needs to be displayed in the Combobox.
Binding combobox to display source and binding source
How SelectedValue and DisplayMemberPath saved my life
this little tick may helps someone
<ComboBox SelectedIndex="1" SelectedValuePath="Tag" SelectedValue="{Binding SampleDept,Mode=OneWayToSource}" >
<ComboBoxItem Content="8-bit" Tag="8" ></ComboBoxItem>
<ComboBoxItem Content="16-bit" Tag="16" ></ComboBoxItem>
<ComboBoxItem Content="24-bit" Tag="24"></ComboBoxItem>
<ComboBoxItem Content="32-bit" Tag="32"></ComboBoxItem>
</ComboBox>
public class SampleModel{
public int SampleDept{
get { return _sampleDept; }
set {
_sampleDept = value;
OnPropertyChanged("SampleDept");
}
}
}
var listItems = val.Split('$');
DataTemplate dt = new DataTemplate();
var combo = new FrameworkElementFactory(typeof(ComboBox));
combo.SetValue(ComboBox.ItemsSourceProperty, listItems);
combo.SetValue(ComboBox.SelectedValueProperty, "Whatever");
combo.SetBinding(ComboBox.SelectedValueProperty, new Binding("Value") { Source = mkvc });
dt.VisualTree = combo;
dt.Seal();
add this to editor template of whatever you want to add combobox to it => mkvc is a class for holding my data
PropertyDefinition pd = new PropertyDefinition();
pd.EditorTemplate = dt;
//rpg =>radPropertyGrid
rpg.PropertyDefinitions.Add(pd);
rpg.Item = propertyList;
propertylist is list of myclass

Categories

Resources