Binding SelectedItem of Combobox in wpf [duplicate] - c#

What is the difference betweeen the following:
SelectedItem
SelectedValue
SelectedValuePath
All these dependency properties are defined in Selector class. I often confuse SelectedItem with SelectedValue , and SelectedValue with SelectedValuePath.
I would like to know the difference between them, and also when do we use them, especially SelectedValue and SelectedValuePath. Please explain their use with some simple examples.

Their names can be a bit confusing :). Here's a summary:
The SelectedItem property returns the entire object that your list is bound to. So say you've bound a list to a collection of Category objects (with each Category object having Name and ID properties). eg. ObservableCollection<Category>. The SelectedItem property will return you the currently selected Category object. For binding purposes however, this is not always what you want, as this only enables you to bind an entire Category object to the property that the list is bound to, not the value of a single property on that Category object (such as its ID property).
Therefore we have the SelectedValuePath property and the SelectedValue property as an alternative means of binding (you use them in conjunction with one another). Let's say you have a Product object, that your view is bound to (with properties for things like ProductName, Weight, etc). Let's also say you have a CategoryID property on that Product object, and you want the user to be able to select a category for the product from a list of categories. You need the ID property of the Category object to be assigned to the CategoryID property on the Product object. This is where the SelectedValuePath and the SelectedValue properties come in. You specify that the ID property on the Category object should be assigned to the property on the Product object that the list is bound to using SelectedValuePath='ID', and then bind the SelectedValue property to the property on the DataContext (ie. the Product).
The example below demonstrates this. We have a ComboBox bound to a list of Categories (via ItemsSource). We're binding the CategoryID property on the Product as the selected value (using the SelectedValue property). We're relating this to the Category's ID property via the SelectedValuePath property. And we're saying only display the Name property in the ComboBox, with the DisplayMemberPath property).
<ComboBox ItemsSource="{Binding Categories}"
SelectedValue="{Binding CategoryID, Mode=TwoWay}"
SelectedValuePath="ID"
DisplayMemberPath="Name" />
public class Category
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Product
{
public int CategoryID { get; set; }
}
It's a little confusing initially, but hopefully this makes it a bit clearer... :)
Chris

To answer a little more conceptually:
SelectedValuePath defines which property (by its name) of the objects bound to the ListBox's ItemsSource will be used as the item's SelectedValue.
For example, if your ListBox is bound to a collection of Person objects, each of which has Name, Age, and Gender properties, SelectedValuePath=Name will cause the value of the selected Person's Name property to be returned in SelectedValue.
Note that if you override the ListBox's ControlTemplate (or apply a Style) that specifies what property should display, SelectedValuePath cannot be used.
SelectedItem, meanwhile, returns the entire Person object currently selected.
(Here's a further example from MSDN, using TreeView)
Update: As #Joe pointed out, the DisplayMemberPath property is unrelated to the Selected* properties. Its proper description follows:
Note that these values are distinct from DisplayMemberPath (which is defined on ItemsControl, not Selector), but that property has similar behavior to SelectedValuePath: in the absence of a style/template, it identifies which property of the object bound to item should be used as its string representation.

SelectedItem and SelectedValue are an object.
and SelectedValuePath is a string.
for example using the ListBox:
Below listbox1.SelectedValue becomes a string value.
string value = listbox1.SelectedValue;
if you say give me listbox1.SelectedItem it will give you the entire object.
ListItem item = listbox1.SelectedItem;
string value = item.value;

inspired by this question I have written a blog along with the code snippet here. Below are some of the excerpts from the blog
SelectedItem – Selected Item helps to bind the actual value from the DataSource which will be displayed. This is of type object and we can bind any type derived from object type with this property. Since we will be using the MVVM binding for our combo boxes in that case this is the property which we can use to notify VM that item has been selected.
SelectedValue and SelectedValuePath – These are the two most confusing and misinterpreted properties for combobox. But these properties come to rescue when we want to bind our combobox with the value from already created object. Please check my last scenario in the following list to get a brief idea about the properties.

Every control that uses Collections to store data have SelectedValue, SelectedItem property. Examples of these controls are ListBox, Dropdown, RadioButtonList, CheckBoxList.
To be more specific if you literally want to retrieve Text of Selected Item then you can write:
ListBox1.SelectedItem.Text;
Your ListBox1 can also return Text using SelectedValue property if value has set to that before. But above is more effective way to get text.
Now, the value is something that is not visible to user but it is used mostly to store in database. We don't insert Text of ListBox1, however we can insert it also, but we used to insert value of selected item. To get value we can use
ListBox1.SelectedValue
Source

Related

Combo Box Two Way Binding resets Properties

I have a combo box in a datagrid located in an activity. Based on combobox selection I populate another grid with controls programatically. User enters some data in these controls and then saves it. The object that the combo box is bound has many properties of which two are used in selected value path and display member path. The data is bound using two way binding for combo box. When the saved activity that has been placed on a workflow is reopened the data is reloaded correctly and the correct object is value is set in the combo box. But on UI rendering only the values that are attached with the combo box remain intact (i.e those in selected value path and display member path) the rest are reset.
Any idea why this might be happening?
P.S: Setting the binding to OneTime solves the problem of retrieval but any changes that are made on the UI after loading are not reflected back.
Code-Behind:
public ObservableCollection<MyRule> AllRules {get;set;}
public MyRule myRule{get;set;}
In datagrid Loaded Event I populate the AllRules as:
AllBusinessRules.Add(new MyRule () { RuleId = item.Id, RuleName = item.Name});
where item.Id and item.Name are obtained from the database via service call.
In the same event if I also load any previously saved rules as:
myRule=SelectedRule;
where SelectedRule has RuleId, RuleName, Inputs and Outputs as well.
Code:
<ComboBox
ItemsSource="{Binding Path=AllRules}"
SelectedItem="{Binding Path=myRule,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
SelectedValuePath="RuleId"
DisplayMemberPath="RuleName">
<DataTemplate>
<TextBox Text="{Binding Path=myRule.RuleName}"/>
</DataTemplate>
</ComboBox>
Class:
public class MyRule{
public int RuleId{get;set;}
public string RuleName{get;set;}
public List<string> Inputs{get;set;} //properties that are reset when the UI renders
public List<string> Outputs{get;set;} //properties that are reset when the UI renders
}
The Inputs and Outputs properties are obtained from the programatically generated controls via reflection and added to the object populated by combobox and saved.
I have studied about this problem here but the solution does not solve my problem. Any help would be great.
SelectedValuePath, DisplayMemberPath are set wrongly. DisplayMemberPath should be "RuleName". SelectedValue, SelectedValuePath are not needed as you have set SelectedItem. SelectedItem will get the chosen item automatically because of Binding. From the myRule object you can access other properties.
It took a lot of time to investigate what was wrong but now that I know its just quite simple.
As I have shown that in the datagrid's Loaded event I used to set the ItemsSource of the combo box and in the item source I have only set the properties RuleId and RuleName.
Problem:
So the problem was that when I assigned the value i.e the selected value on reloading the combobox e.g. myRule=SelectedRule the other properties i.e. Inputs and Outputs are not there in the ItemsSource. That is why the selected object though correct did not have Inputs and Outputs as the SelectedItem was from ItemsSource of the Combo Box giving me the impression that the two way binding had somehow reset the values of properties not bound with the combo box.
Solution:
In the end I wrapped my MyRule Object in another object like RuleInformation i.e
public class RuleInformation{
public List<string> Inputs;
public List<string> Outputs;
public MyRule myRule{get;set;}
}
where MyRule is like:
public class MyRule{
public int RuleId{get;set;}
public string RuleName{get;set;}
}
So the combo box is bound to the MyRule object whereas the inputs and output properties remain untouched in the upper object.

DevExpress RepositoryItemLookUpEdit

I am binding the Grid with a business object which contains a field Country (which is another business object containing ID and Name). I want to display the country name set to the "Country" in the business object for each row. However if the user wishes to change the country then I want to show the user a drop down list with all the countries available.
I'm stuck with getting the SlectedValue from the repositoryItemLookUpEdit and setting the Selected value
All you should have to do is assign a RepositoryItemLookupEdit to the Column.Edit property.
Then in your RepositoryItemLookupEdit set the Datasource to a IList of all your Country objects.
Set the RepositoryItemLookupEdit.DisplayMember to "Name" and leave ValueMember as blank (this will make the object itself the value)
Then your grid should handle everything for you, as if you click on the dropdown and select a new country the selected Country object will be assigned to that cell's value.
Keep in mind however that the Objects much be the same Reference match... ie. If your Business Objects Country object isn't apart of the IList of Countries then it won't display a value.
Are you using XPO at all?
I Solved this using a ComboBox instead of a LookupEdit and it worked without problem.

Combo Box in Silverlight 4

I have a combo box that is bound to a collection that is essentially a list of Name/Value pairs. The collection can have multiple items with different names, but the values may be the same.
public class NameValuePair
{
public string Name { get; set; }
public string Value { get; set; }
}
public class NameValuePairCollection : List<NameValuePair>
{
public NameValuePairCollection(): base() { }
}
So inside my User Control I have a private field called items which is an instance of that NameValuePair collection:
private NameValuePairCollection items = new NameValuePairCollection()
Somewhere along the lines that collection gets initialized and items get added to it. However, the problem I see is when I try to set the selected index of the combo box that is bound to this collection:
this.CboItemsSelector.SelectedIndex = 3;
or
this.CboItemsSelector.SelectedItem = this.items[3];
The selected item is there but the UI is not synchronized. The UI's selector still defaults to the first item in the list, even thought the SelectedItem's Name and Value properties DO IN FACT CORRESPOND to whatever is in index 3 of the underlying collection!
Any ideas on how to force the ComboBox to refresh itself? Or just plain fix the issue? I know it's quite small issue, but it is big enough to force me to rewrite quite a bit of code.... :( :( :(
Thanks!
You need to inherit from ObservableCollection, not List. Otherwise no OnPropertyChanged events will be fired and the bound control wont know the data has been updated.
Do the selected Item's Name and Value properties match or is the SelectedItem an instance from within the same collection? .Net will not know to compare the items by name and value unless you tell it to, else it will use object equality to try and find the item in your list. If you are setting the selected item to an instance that is not actually in the list (but has the same properties) .net will not find it in the list. You have 2 options, override equality for your object and force comparison of properties, or ensure that you always set the selected item to an item in the list. Also try what Andy May suggested and do 2 way binding on the ItemsSource and on the SelectedItem, should work then

Checked List Box with data value property for each item?

Does anyone know of a control such as a Checked List Box where each item can have a value against it.
For example you have a list of fruits and in the listbox it displays Apple, Orange & Banana but the values for those items are A, O & B.
The CheckedListBox control can already do that. Its Items collection accepts any object that derives from System.Objects. The objects are displayed in the list using the value returned from their ToString method.
Therefore, you can create your own custom classes and add them to the CheckedListBox. Make sure that you overload the ToString method to return the string you want to be displayed in the list box. Then, you can add any other methods or properties to the class that you want. When you get a reference to a selected item, you can cast it to your Fruit class and call any method you want.
I think this is default functionality for .Net Listboxes, comboboxes etc.
If your Listbox has a datasource with items which have properties FruitName and FruitId you can set the DisplayMember to FruitName and the ValueMember to FruitId.
On selecting an item the SelectedValue will be the FruitId.
What platform? If it is HTML, then the <select /> tag can have a different value and display string.
If you are working with Winforms, you can set the ListBox to have any type of object. so you could make a class that has a string for display and some kind of object for its value. Then override the ToString() method and return the display string and there you go!

How can I set the selected index of a comboBox base from its valueMember? (C# Window Form)

I have a comboBox that displays different Municipalities (these Municipalities belongs to a particular Province) in our country. Since there are Municipalities having the same name, I binded the "MunicipalityName" (a table column from 'MUNICIPALITY' table in my database) to DisplayMember property of the comboBox and "Municipality_ID" to ValueMember property of the comboBox.
When the user saves his details, I supply the SelectedValue from ValueMember of the MUNICIPALITY and insert it to Employee table.
cmd.Parameters.Add(new SqlParameter("#Municipality_ID", (object)comboBoxMunicipality.SelectedValue.ToString()));
I find it hard when it comes to retrieval of data when an Employee needs to update his information. I have to manually check the Municipality_ID of that employee and compare it to the binded data in the comboBox, then loop through it, determine what index that Municipality_ID located, and set the SelectedIndex property of the comboBox. (Quiet lengthy compared to code snippet below)
I have this code, but I find conflicts since Municipality_Name is not unique.
//set SelectedIndex based from DisplayMember of the comboBox
comboBoxMunicipality.SelectedIndex = comboBoxMunicipality.FindStringExact(dataTable.Rows[0]["MunicipalityName"].ToString());
Is there a way to set the SelectedIndex of the comboBox like the code above, but this time, comparing it to the ValueMember?
Is there a shortcut?
//something like this?
comboBoxMunicipality.SelectedIndex =
comboBoxMunicipality.FindByValue(dataTable.Rows[0]["Municipality_ID"].ToString());
I hope you get my point guys... Please help. Thanks.
How about this?
comboBoxMunicipality.SelectedValue = theMunicipalityIDtoSelect

Categories

Resources