Skip to content

Commit

Permalink
Fix breaking ABI changes
Browse files Browse the repository at this point in the history
- return for AddPropertyEvent is now void like before to avoid ABI breaks
- Use PropertyBinding to wire up property events in DelegateBinding so it supports both INotifyPropertyChanged and MyPropertyChanged events
  • Loading branch information
cwensley committed Sep 15, 2024
1 parent f9b4a85 commit 43a1912
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 23 deletions.
21 changes: 8 additions & 13 deletions src/Eto/Forms/Binding/Binding.helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,18 +189,15 @@ public static IndirectBinding<TValue> Property<TValue>(string propertyName, bool
/// <param name="obj">INotifyPropertyChanged object to attach the event handler to</param>
/// <param name="propertyName">Name of the property to trigger the changed event.</param>
/// <param name="eh">Event handler delegate to trigger when the specified property changes</param>
/// <returns>Object to pass to RemovePropertyEvent to unregister the event</returns>
/// <seealso cref="RemovePropertyEvent(object,EventHandler{EventArgs})"/>
/// <seealso cref="RemovePropertyEvent(object,string,EventHandler{EventArgs})"/>
public static object AddPropertyEvent(object obj, string propertyName, EventHandler<EventArgs> eh)
public static void AddPropertyEvent(object obj, string propertyName, EventHandler<EventArgs> eh)
{
if (obj is INotifyPropertyChanged notifyObject)
{
var helper = new PropertyNotifyHelper(notifyObject, propertyName);
helper.Changed += eh;
return helper;
}
return null;
}

/// <summary>
Expand All @@ -214,27 +211,25 @@ public static object AddPropertyEvent(object obj, string propertyName, EventHand
/// <param name="obj">INotifyPropertyChanged object to attach the event handler to</param>
/// <param name="propertyExpression">Expression to the property to trigger the changed event.</param>
/// <param name="eh">Event handler delegate to trigger when the specified property changes</param>
/// <returns>Object to pass to RemovePropertyEvent to unregister the event</returns>
/// <seealso cref="RemovePropertyEvent(object,EventHandler{EventArgs})"/>
/// <seealso cref="RemovePropertyEvent{T,TProperty}(T,Expression{Func{T, TProperty}},EventHandler{EventArgs})"/>
public static object AddPropertyEvent<T, TProperty>(T obj, Expression<Func<T, TProperty>> propertyExpression, EventHandler<EventArgs> eh)
public static void AddPropertyEvent<T, TProperty>(T obj, Expression<Func<T, TProperty>> propertyExpression, EventHandler<EventArgs> eh)
{
var propertyInfo = propertyExpression.GetMemberInfo();
if (propertyInfo != null)
{
return AddPropertyEvent(obj, propertyInfo.Member.Name, eh);
AddPropertyEvent(obj, propertyInfo.Member.Name, eh);
}
return null;
}

/// <summary>
/// Removes an event handler previously attached with the AddPropertyEvent method.
/// </summary>
/// <remarks>
/// Note that if you pass the object that the event is attached to instea of the object returned from AddPropertyEvent,
/// then this will unsubscribe from all property handlers that point to the same delegate specified by <paramref name="eh"/>
/// Note that this will unsubscribe from all property handlers that point to the same delegate specified by <paramref name="eh"/>.
/// Use <see cref="RemovePropertyEvent(object, string, EventHandler{EventArgs})"/> to only unsubscribe for a single property.
/// </remarks>
/// <param name="obj">Object returned from AddPropertyEvent to unsubscribe, or the object the event is subscribed to</param>
/// <param name="obj">Object the event is subscribed to</param>
/// <param name="eh">Event handler delegate to remove</param>
/// <seealso cref="AddPropertyEvent(object,string,EventHandler{EventArgs})"/>
public static void RemovePropertyEvent(object obj, EventHandler<EventArgs> eh)
Expand Down Expand Up @@ -266,7 +261,7 @@ public static void RemovePropertyEvent(object obj, EventHandler<EventArgs> eh)
/// <summary>
/// Removes an event handler previously attached with the AddPropertyEvent method.
/// </summary>
/// <param name="obj">Object returned from AddPropertyEvent to unsubscribe</param>
/// <param name="obj">INotifyPropertyChanged object to unsubscribe from</param>
/// <param name="propertyExpression">Expression for the property to remove the event handler for</param>
/// <param name="eh">Event handler delegate to remove</param>
/// <seealso cref="AddPropertyEvent{T,TProperty}(T,Expression{Func{T, TProperty}},EventHandler{EventArgs})"/>
Expand All @@ -282,7 +277,7 @@ public static void RemovePropertyEvent<T, TProperty>(T obj, Expression<Func<T, T
/// <summary>
/// Removes an event handler previously attached with the AddPropertyEvent method.
/// </summary>
/// <param name="obj">Object returned from AddPropertyEvent to unsubscribe</param>
/// <param name="obj">INotifyPropertyChanged object to unsubscribe from</param>
/// <param name="propertyName">Name of the property to remove the event handler for</param>
/// <param name="eh">Event handler delegate to remove</param>
/// <seealso cref="AddPropertyEvent(object,string,EventHandler{EventArgs})"/>
Expand Down
5 changes: 3 additions & 2 deletions src/Eto/Forms/Binding/DelegateBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,9 @@ public class DelegateBinding<T, TValue> : IndirectBinding<TValue>
DefaultSetValue = defaultSetValue;
if (!string.IsNullOrEmpty(notifyProperty))
{
AddChangeEvent = (obj, eh) => { AddPropertyEvent(obj, notifyProperty, eh); return obj; };
RemoveChangeEvent = (obj, eh) => RemovePropertyEvent(obj, eh);
var binding = new PropertyBinding<object>(notifyProperty);
AddChangeEvent = (obj, eh) => binding.AddValueChangedHandler(obj, eh);
RemoveChangeEvent = (obj, eh) => binding.RemoveValueChangedHandler(obj, eh);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Eto/Forms/Binding/PropertyNotifyHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Eto.Forms;
/// </summary>
/// <remarks>
/// Use <see cref="Binding.AddPropertyEvent"/> and <see cref="Binding.RemovePropertyEvent(object,string,EventHandler{EventArgs})"/> to access
/// this functionality.
/// this functionality, or better yet use the <see cref="PropertyBinding{T}"/> class.
/// </remarks>
class PropertyNotifyHelper
{
Expand Down
14 changes: 7 additions & 7 deletions test/Eto.Test/UnitTests/Forms/Bindings/BindingHelpersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public void RemovingAPropertyEventShouldWork()
void Handler(object sender, EventArgs e) => propertyValueChanged = true;

var bindObject = new BindObject { BoolProperty = true };
var obj = Binding.AddPropertyEvent(bindObject, obj => obj.BoolProperty, Handler);
Binding.AddPropertyEvent(bindObject, obj => obj.BoolProperty, Handler);

// Act
Binding.RemovePropertyEvent(bindObject, Handler);
Expand All @@ -107,9 +107,9 @@ public void RemovingAPropertyEventShouldKeepOtherEvents()
void StringHandler(object sender, EventArgs e) => stringPropertyValueChanged = true;

var bindObject = new BindObject { BoolProperty = true, IntProperty = 3, StringProperty = "Test1" };
var boolObj = Binding.AddPropertyEvent(bindObject, obj => obj.BoolProperty, BoolHandler);
var intObj = Binding.AddPropertyEvent(bindObject, obj => obj.IntProperty, IntHandler);
var stringObj = Binding.AddPropertyEvent(bindObject, obj => obj.StringProperty, StringHandler);
Binding.AddPropertyEvent(bindObject, obj => obj.BoolProperty, BoolHandler);
Binding.AddPropertyEvent(bindObject, obj => obj.IntProperty, IntHandler);
Binding.AddPropertyEvent(bindObject, obj => obj.StringProperty, StringHandler);

// Act
Binding.RemovePropertyEvent(bindObject, IntHandler);
Expand All @@ -134,9 +134,9 @@ public void RemovingAllPropertyEventsShouldWork()
void StringHandler(object sender, EventArgs e) => stringPropertyValueChanged = true;

var bindObject = new BindObject { BoolProperty = true, IntProperty = 3, StringProperty = "Test1" };
var boolObj = Binding.AddPropertyEvent(bindObject, obj => obj.BoolProperty, BoolHandler);
var intObj = Binding.AddPropertyEvent(bindObject, obj => obj.IntProperty, IntHandler);
var stringObj = Binding.AddPropertyEvent(bindObject, obj => obj.StringProperty, StringHandler);
Binding.AddPropertyEvent(bindObject, obj => obj.BoolProperty, BoolHandler);
Binding.AddPropertyEvent(bindObject, obj => obj.IntProperty, IntHandler);
Binding.AddPropertyEvent(bindObject, obj => obj.StringProperty, StringHandler);

// Act
Binding.RemovePropertyEvent(bindObject, StringHandler);
Expand Down

0 comments on commit 43a1912

Please sign in to comment.