How IEQuatable<T> affect the behavior of combobox
While working on combo box I found out a wired issue. Xaml looks like this
<ComboBox x:Name="cb" ItemsSource="{Binding MyEntity.Choices}"
SelectedItem="{Binding MyEntity.Choice,Mode=TwoWay}"
Height="25"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"/>
Let’s say Itemsource is binded with a List of Shaft (object) & selectedItem is one among the list.
public partial class MainWindow : Window
{
private ShaftsData shaftData;
public ShaftsData ShaftData
{
get { return shaftData; }
set { shaftData = value; }
}
public MainWindow()
{
ShaftData = new ShaftsData();
InitializeComponent();
txtBox.Text = "Default";
this.DataContext = this;
SetComboCollectionAndSelectedShaft();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
shaftData.ComboCollection = null;
}
private void SetComboCollectionAndSelectedShaft()
{
Collection<Shaft> myCollection = new Collection<Shaft>();
for (int i = 1; i <= 5; ++i)
{
Shaft sh = new Shaft();
sh.Id = i;
sh.Name = string.Format("{0} {1} ", txtBox.Text, i);
myCollection.Add(sh);
}
shaftData.ComboCollection = myCollection;
shaftData.SelectedShaft = shaftData.ComboCollection[0];
}
}
public class ShaftsData : INotifyPropertyChanged
{
private Collection<Shaft> _comboCollection;
private Shaft _selectedShaft;
public Collection<Shaft> ComboCollection
{
get
{
return _comboCollection;
}
set
{
_comboCollection = value;
OnPropertyChanged("ComboCollection");
}
}
public Shaft SelectedShaft
{
get { return _selectedShaft; }
set
{
_selectedShaft = value;
OnPropertyChanged("SelectedShaft");
}
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
And then I tried to make this list to null (Please refe开发者_开发知识库r to Button_Click) .Combobox is calling the .Equals of each object of the List & compare the last Selected object. While my expectation is it should not call .equals & set the SelectedItem to null.
public class Shaft
{
private int _id;
private string _name;
public int Id {
get { return _id; }
set {
_id = value;
}
}
public string Name
{
get { return _name; }
set
{
_name = value;
}
}
public override string ToString()
{
return _name;
}
public override bool Equals(object obj)
{
System.Diagnostics.Debug.WriteLine("Calling from object.Equals");
Shaft shaft = obj as Shaft;
if (null != shaft)
{
System.Diagnostics.Debug.WriteLine("Equals called for " + this.Name + ". Compared with " + shaft.Name);
}
else
{
System.Diagnostics.Debug.WriteLine("Equals called for " + this + ". Compared with " + shaft);
}
return base.Equals(obj);
}
Now if I implement IEquatable on Shaft & then set the List to null it works fine. Means no call is going to .Eqauls & selectedItem is set to null.
New Implementation
public class Shaft : IEquatable<Shaft>
{
private int _id;
private string _name;
public int Id {
get { return _id; }
set {
_id = value;
}
}
public string Name
{
get { return _name; }
set
{
_name = value;
}
}
public override string ToString()
{
return _name;
}
public bool Equals(Shaft shaft)
{
System.Diagnostics.Debug.WriteLine("Calling from object.Equals");
// Shaft shaft = obj as Shaft;
if (null != shaft)
{
System.Diagnostics.Debug.WriteLine("Equals called for " + this.Name + ". Compared with " + shaft.Name);
}
else
{
System.Diagnostics.Debug.WriteLine("Equals called for " + this + ". Compared with " + shaft);
}
return base.Equals(shaft);
}
}
}
This shows that the combobox is not releasing the objects binded to Itemsource even if the list is null. Until we implements IEquatable .
Any idea why it is like that?
The behaviour upon Button_Click is identical for both implementations. How did you know there were no calls to Object.Equals if you didn't override it in the second case?
As for not "releasing" objects this looks to be a known issue of WPF: http://support.microsoft.com/kb/938416
As a workaround you can do one of the following:
- call Collection.Clear method instead of setting collection reference to null
- use ObservableCollection instead of Collection
精彩评论