I have a ComboBox in wpf that twoway binds between the view and viewmodel.
Running under .net 4 in win7 everything was working as expected but running my application under windows 8, the combobox can’t seem to get the correct selected item from the viewmodel.
When entering the view the combobox asks for the selected item from the view model
The selected item is returned and my method that overrides “Equals” returns true.
The combobox in the view then either doesn’t register this or does and then ignores it and the next thing that happens is that the View sets the “Selected Item” in the view model to “NULL”.
Is there another way I can achieve the requirements or is it just a bug in running .net 4 apps under .net 4.5 that I’m going to have to live with?
Here is the source. NOTE I bind to the item class and not the enum directly so I can access the [Description] tag for better item names in my combobox.
View
<Controls:KNComboBox Style="{DynamicResource FlowMenuComboBox}" SelectedItem="{Binding ItemsOrder}" ItemsSource="{Binding ItemsOrderValues}" Margin="10,0,0,10"
DisplayMemberPath="Description" SelectedValuePath="{Binding Path=EnumObject}" DisplayString="Sort By:"/>
View Model
private ItemsOrderByItem _itemsOrder;
public ItemsOrderByItem ItemsOrder
{
get
{
return _itemsOrder;
}
set
{
_itemsOrder = value;
RaisePropertyChanged("ItemsOrder");
//Methods Called Here Not Important To Question
}
}
public List<ItemsOrderByItem> ItemsOrderValues
{
get
{
List<ItemsOrderByItem> enumItems = new List<ItemsOrderByItem>();
foreach (ItemsOrderBy enumValue in Enum.GetValues(typeof(ItemsOrderBy)))
{
enumItems.Add(new ItemsOrderByItem(enumValue));
}
return enumItems;
}
}
The Enum
public enum ItemsOrderBy
{
[Description("Name")]
Name,
[Description("Date Added")]
DateAdded
}
The Item Class
public class ItemsOrderByItem
{
public ItemsOrderByItem(ItemsOrderBy enumValue)
{
EnumObject = enumValue;
}
public ItemsOrderBy EnumObject;
public string Description
{
get
{
return EnumExtension.GetEnumDescription<ItemsOrderBy>(EnumObject);
}
}
public override string ToString()
{
return Description;
}
public override bool Equals(object obj)
{
if (obj is ItemsOrderByItem)
{
return ((ItemsOrderByItem)obj).EnumObject == EnumObject;
}
else
{
return false;
}
}
}
Inspection of the code snippets in your post reveals several problems:
ItemsOrderValues property returns a new value each time it is queried. This is equivalent to changing the value without raising a property-changed notification. Data-binding clients will be confused.
{Binding Path=EnumObject} won’t work. Binding paths use properties; EnumObject is a field.
SelectedValuePath has type string. The binding to EnumObject (if it worked) produces an object of type ItemsOrderBy. After type-conversion, this will set SelectedValuePath to “Name” (or possibly “ItemsOrderBy.Name”). This is legal, but probably not what you wanted. The path is applied to items in the ItemsSource, which have type ItemsOrderByItem; this type doesn’t have a property called “Name”.
The ItemsOrderByItem class has mutable equality semantics, i.e. the result of Object.Equals(x, y) can change, for fixed objects x and y. That’s because the Equals method depends on a publicly-mutable field – EnumObject. This will confuse any code that (legitimately) assumes that once x and y have tested Equal, they will remain Equal.
The class overrides Equals, but doesn’t override GetHashCode. This is forbidden (see docs for either method) because it leads to horrible confusion whenever instances are used in hashtables. Two instances that are Equal but have different hashcodes will corrupt a hashtable. [When you fix this, remember to ensure that an object’s hashcode never changes – this is also a documented requirement.]
Of these, the last one is probably most responsible for your problem. WPF uses hashtables to help represent the set of selected items, and the exact usage has changed in v4.5. It’s very likely that the unreliable hashing behavior of the ItemsOrderByItem class is causing the confusion.
If fixing these coding issues still doesn’t solve your problem, please feel free to open connect bug with the repro project.