I've simplified my code to the following short example that reproduce the error. I'm trying to bind a value of a derived class to a control. The derived class and the binding logic are:
bindingSource = new BindingSource();
numericUpDown1.DataBindings.Add("Value", bindingSource, nameof(SinglePoint.Val), false, DataSourceUpdateMode.OnPropertyChanged);
bindingSource.DataSource = new[] { new SinglePoint(100) };
[...]
public class SinglePoint : PointList
{
public SinglePoint(int val) { points.Add(val); }
public int Val
{
get { return points[0]; }
set
{
if (value > 300) value = 300; //(*)
points[0] = value;
}
}
}
As a result, when setting for instance a value of 500 on the NumericUpDown, after leaving it we should see 300 because of line (*). This works if the base class does not implement GetHashCode:
public class PointList
{
protected List<int> points = new List<int>();
public PointList() { }
// UNCOMMENT this and the binding will stop working properly
//public override int GetHashCode()
//{
// unchecked
// {
// int hashCode = 17;
// foreach (var item in points)
// hashCode += 13 * item.GetHashCode();
// return hashCode;
// }
//}
}
However, if you try to uncomment the GetHashCode implementation, the binding will break. Meaning that after setting 500 and leaving the NumericUpDown, the control will still show 500, but in reality the underlying value will be 300. Why is this happening and how could I solve it without turning down my custom implementation of GetHashCode?
EDIT
As pointed out by some of you, GetHashCode should not change because it is used by the binding mechanism. This reply to the first part of my question. However, how can I make my PointList class satisfying the other rule by which "if two things are equal (Equals(...) == true) then they must return the same value for GetHashCode()". If I have two PointList objects with the same list (sequence) of points I would like them to be found equal (because of other logics in my code), which should imply having the same hash code. How would you do?
WinForms uses the hashcode of the data object and data member to generate a key, which is used to track the data-binded-object in an internal storage. If you change the hash-calculation so that the hash changes when a data member changes value, then previously-generated-key is not updated with it, and is therefor different than the current key. This breaks the data-binding-mechanism.
Source: http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/BindingContext.cs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With