99
1010using System ;
1111using System . Collections . Generic ;
12+ using System . Linq . Expressions ;
1213using System . Runtime . CompilerServices ;
1314using Microsoft . Toolkit . Mvvm . Messaging ;
1415using Microsoft . Toolkit . Mvvm . Messaging . Messages ;
@@ -140,7 +141,18 @@ protected virtual void Broadcast<T>(T oldValue, T newValue, string? propertyName
140141 /// </remarks>
141142 protected bool SetProperty < T > ( ref T field , T newValue , bool broadcast , [ CallerMemberName ] string ? propertyName = null )
142143 {
143- return SetProperty ( ref field , newValue , EqualityComparer < T > . Default , broadcast , propertyName ) ;
144+ T oldValue = field ;
145+
146+ // We duplicate the code as in the base class here to leverage
147+ // the intrinsics support for EqualityComparer<T>.Default.Equals.
148+ bool propertyChanged = SetProperty ( ref field , newValue , propertyName ) ;
149+
150+ if ( propertyChanged && broadcast )
151+ {
152+ Broadcast ( oldValue , newValue , propertyName ) ;
153+ }
154+
155+ return propertyChanged ;
144156 }
145157
146158 /// <summary>
@@ -158,21 +170,16 @@ protected bool SetProperty<T>(ref T field, T newValue, bool broadcast, [CallerMe
158170 /// <returns><see langword="true"/> if the property was changed, <see langword="false"/> otherwise.</returns>
159171 protected bool SetProperty < T > ( ref T field , T newValue , IEqualityComparer < T > comparer , bool broadcast , [ CallerMemberName ] string ? propertyName = null )
160172 {
161- if ( ! broadcast )
162- {
163- return SetProperty ( ref field , newValue , comparer , propertyName ) ;
164- }
165-
166173 T oldValue = field ;
167174
168- if ( SetProperty ( ref field , newValue , comparer , propertyName ) )
175+ bool propertyChanged = SetProperty ( ref field , newValue , comparer , propertyName ) ;
176+
177+ if ( propertyChanged && broadcast )
169178 {
170179 Broadcast ( oldValue , newValue , propertyName ) ;
171-
172- return true ;
173180 }
174181
175- return false ;
182+ return propertyChanged ;
176183 }
177184
178185 /// <summary>
@@ -216,19 +223,61 @@ protected bool SetProperty<T>(T oldValue, T newValue, Action<T> callback, bool b
216223 /// <returns><see langword="true"/> if the property was changed, <see langword="false"/> otherwise.</returns>
217224 protected bool SetProperty < T > ( T oldValue , T newValue , IEqualityComparer < T > comparer , Action < T > callback , bool broadcast , [ CallerMemberName ] string ? propertyName = null )
218225 {
219- if ( ! broadcast )
226+ bool propertyChanged = SetProperty ( oldValue , newValue , comparer , callback , propertyName ) ;
227+
228+ if ( propertyChanged && broadcast )
220229 {
221- return SetProperty ( oldValue , newValue , comparer , callback , propertyName ) ;
230+ Broadcast ( oldValue , newValue , propertyName ) ;
222231 }
223232
224- if ( SetProperty ( oldValue , newValue , comparer , callback , propertyName ) )
233+ return propertyChanged ;
234+ }
235+
236+ /// <summary>
237+ /// Compares the current and new values for a given nested property. If the value has changed,
238+ /// raises the <see cref="ObservableObject.PropertyChanging"/> event, updates the property and then raises the
239+ /// <see cref="ObservableObject.PropertyChanged"/> event. The behavior mirrors that of
240+ /// <see cref="ObservableObject.SetProperty{T}(Expression{Func{T}},T,string)"/>, with the difference being that this
241+ /// method is used to relay properties from a wrapped model in the current instance. For more info, see the docs for
242+ /// <see cref="ObservableObject.SetProperty{T}(Expression{Func{T}},T,string)"/>.
243+ /// </summary>
244+ /// <typeparam name="T">The type of property to set.</typeparam>
245+ /// <param name="propertyExpression">An <see cref="Expression{TDelegate}"/> returning the property to update.</param>
246+ /// <param name="newValue">The property's value after the change occurred.</param>
247+ /// <param name="broadcast">If <see langword="true"/>, <see cref="Broadcast{T}"/> will also be invoked.</param>
248+ /// <param name="propertyName">(optional) The name of the property that changed.</param>
249+ /// <returns><see langword="true"/> if the property was changed, <see langword="false"/> otherwise.</returns>
250+ protected bool SetProperty < T > ( Expression < Func < T > > propertyExpression , T newValue , bool broadcast , [ CallerMemberName ] string ? propertyName = null )
251+ {
252+ return SetProperty ( propertyExpression , newValue , EqualityComparer < T > . Default , broadcast , propertyName ) ;
253+ }
254+
255+ /// <summary>
256+ /// Compares the current and new values for a given nested property. If the value has changed,
257+ /// raises the <see cref="ObservableObject.PropertyChanging"/> event, updates the property and then raises the
258+ /// <see cref="ObservableObject.PropertyChanged"/> event. The behavior mirrors that of
259+ /// <see cref="ObservableObject.SetProperty{T}(Expression{Func{T}},T,IEqualityComparer{T},string)"/>,
260+ /// with the difference being that this method is used to relay properties from a wrapped model in the
261+ /// current instance. For more info, see the docs for
262+ /// <see cref="ObservableObject.SetProperty{T}(Expression{Func{T}},T,IEqualityComparer{T},string)"/>.
263+ /// </summary>
264+ /// <typeparam name="T">The type of property to set.</typeparam>
265+ /// <param name="propertyExpression">An <see cref="Expression{TDelegate}"/> returning the property to update.</param>
266+ /// <param name="newValue">The property's value after the change occurred.</param>
267+ /// <param name="comparer">The <see cref="IEqualityComparer{T}"/> instance to use to compare the input values.</param>
268+ /// <param name="broadcast">If <see langword="true"/>, <see cref="Broadcast{T}"/> will also be invoked.</param>
269+ /// <param name="propertyName">(optional) The name of the property that changed.</param>
270+ /// <returns><see langword="true"/> if the property was changed, <see langword="false"/> otherwise.</returns>
271+ protected bool SetProperty < T > ( Expression < Func < T > > propertyExpression , T newValue , IEqualityComparer < T > comparer , bool broadcast , [ CallerMemberName ] string ? propertyName = null )
272+ {
273+ bool propertyChanged = SetProperty ( propertyExpression , newValue , comparer , out T oldValue , propertyName ) ;
274+
275+ if ( propertyChanged && broadcast )
225276 {
226277 Broadcast ( oldValue , newValue , propertyName ) ;
227-
228- return true ;
229278 }
230279
231- return false ;
280+ return propertyChanged ;
232281 }
233282 }
234283}
0 commit comments