[Mono-bugs] [Bug 664829] New: Data binding events not unhooked correctly, causing a memory leak in some situations
bugzilla_noreply at novell.com
bugzilla_noreply at novell.com
Sun Jan 16 16:56:36 EST 2011
https://bugzilla.novell.com/show_bug.cgi?id=664829
https://bugzilla.novell.com/show_bug.cgi?id=664829#c0
Summary: Data binding events not unhooked correctly, causing a
memory leak in some situations
Classification: Mono
Product: Mono: Class Libraries
Version: 2.6.x
Platform: x86
OS/Version: Windows 7
Status: NEW
Severity: Normal
Priority: P5 - None
Component: Windows.Forms
AssignedTo: mono-bugs at lists.ximian.com
ReportedBy: cvolzke at live.com.au
QAContact: mono-bugs at lists.ximian.com
Found By: ---
Blocker: ---
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US)
AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.1.249.1036 Safari/532.5
Control and data source events are not unhooked correctly, causing a memory
leak in some circumstances.
Reproducible: Always
Steps to Reproduce:
[Test]
public void Test_DataBindingEventsUnhookedCorrectly()
{
TestDataSource dataSource = new TestDataSource();
Control.DataBindings.Add("ControlValue", dataSource, "IntProperty");
Form.Controls.Add(Control);
Form.Show();
Application.DoEvents();
AssertEquals(true, Control.ControlValueChanged_IsHooked);
AssertEquals(true, dataSource.IntPropertyChanged_IsHooked);
Form.Dispose();
AssertEquals(false, Control.ControlValueChanged_IsHooked);
AssertEquals(false, dataSource.IntPropertyChanged_IsHooked);
}
Form form;
Form Form
{
get { return form ?? (form = new Form()); }
}
TestControl control;
TestControl Control
{
get { return control ?? (control = new TestControl()); }
}
class TestControl : Control
{
public bool ControlValueChanged_IsHooked
{
get { return ControlValueChanged != null; }
}
public event EventHandler ControlValueChanged;
public int ControlValue
{
get
{
int result;
int.TryParse(Text, out result);
return result;
}
set
{
Text = value.ToString();
if (ControlValueChanged != null)
{
ControlValueChanged(this, EventArgs.Empty);
}
}
}
}
class TestDataSource
{
public bool IntPropertyChanged_IsHooked
{
get { return IntPropertyChanged != null; }
}
public event EventHandler IntPropertyChanged;
public const int IntPropertyDefaultValue = 5;
int intProperty = IntPropertyDefaultValue;
public int IntProperty
{
get { return intProperty; }
set
{
intProperty = value;
if (IntPropertyChanged != null)
{
IntPropertyChanged(this, EventArgs.Empty);
}
}
}
}
Actual Results:
Unit test fails
Expected Results:
Unit test should pass, as it does with ms.net.
Code added to Binding.SetControl:
#if NET_2_0
internal void SetControl (IBindableComponent control)
#else
internal void SetControl (Control control)
#endif
{
// ----- code added here ----- //
if (control == null) // when removing the binding
{
// unhook control events
if (this.control != null)
{
this.control.Validating -= new
CancelEventHandler(ControlValidatingHandler);
this.control.HandleCreated -= new
EventHandler(ControlCreatedHandler);
}
// unhook the control ValueChanged event
PropertyDescriptor prop_changed_event2 =
GetPropertyChangedEvent(this.control, property_name);
if (prop_changed_event2 != null)
prop_changed_event2.RemoveValueChanged(this.control, new
EventHandler(ControlPropertyChangedHandler));
// unhook the data source events
if (manager is PropertyManager)
{
PropertyDescriptor prop_changed_event3 =
GetPropertyChangedEvent(manager.Current, binding_member_info.BindingField);
if (prop_changed_event3 != null)
prop_changed_event3.RemoveValueChanged(manager.Current, new
EventHandler(SourcePropertyChangedHandler));
}
return;
}
// ----- code added here ----- //
if (control == this.control)
return;
Code added to ControlBindingsCollection constructor:
public ControlBindingsCollection (IBindableComponent control)
{
bindable_component = control;
// ----- code added here ----- //
// clean up the bindings once the control is disposed
EventDescriptor disposed =
TypeDescriptor.GetEvents(control)["Disposed"];
disposed.AddEventHandler(control, new EventHandler(delegate
{
foreach (Binding binding in this)
{
binding.SetControl(null);
}
}));
// ----- code added here ----- //
this.control = control as Control;
default_datasource_update_mode = DataSourceUpdateMode.OnValidation;
}
Code added to ControlBindingsCollection.RemoveCore:
protected override void RemoveCore (Binding dataBinding) {
if (dataBinding == null)
throw new ArgumentNullException ("dataBinding");
dataBinding.SetControl(null); // line added
base.RemoveCore (dataBinding);
}
--
Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.
More information about the mono-bugs
mailing list