Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c3b3d03
Add initial version of ObservableValidator type
Sergio0694 Aug 13, 2020
67908f3
Update ValidateProperty API to mirror SetProperty
Sergio0694 Aug 13, 2020
ffb54ca
Add XML docs for thrown exceptions
Sergio0694 Aug 13, 2020
f429a78
Removed unnecessary using directive
Sergio0694 Aug 18, 2020
1cb4df2
Speed/memory improvements to SetPropertyAndNotifyOnCompletion
Sergio0694 Aug 19, 2020
06cc520
Added cancelation support for async commands
Sergio0694 Aug 21, 2020
06ca186
Fixed spelling to follow conventions
Sergio0694 Aug 21, 2020
bcb4244
Merge branch 'master' into feature/mvvm-preview2
Sergio0694 Aug 21, 2020
b8610ab
Added unit tests for cancelable async commands
Sergio0694 Aug 21, 2020
38680ea
Removed unnecessary visibility modifiers
Sergio0694 Aug 23, 2020
cfb2628
Temporary reverted FieldAccessor<T> APIs
Sergio0694 Aug 31, 2020
0bd1f92
Removed Ioc class and MS.Ex.DI dependency
Sergio0694 Aug 31, 2020
4144f60
Removed repeated ErrorsChanged event raise
Sergio0694 Sep 2, 2020
fed7051
Added null/"" handling in ObservableValidator.GetErrors
Sergio0694 Sep 2, 2020
b0f6b71
Added TaskAccessor<TTask> API, code refactoring
Sergio0694 Sep 2, 2020
dd4fd4c
Hidden Task/Task<T> type from TaskNotifier
Sergio0694 Sep 3, 2020
51dd094
Minor codegen improvements in TaskNotifier
Sergio0694 Sep 3, 2020
434a128
Minor codegen improvement in SetProperty with Action<T>
Sergio0694 Sep 3, 2020
be877f2
Speed improvements in wrapping SetProperty<T>
Sergio0694 Sep 3, 2020
a8293f7
Minor codegen improvements for EqualityComparer<T>
Sergio0694 Sep 3, 2020
0358dc5
Merge branch 'feature/mvvm-preview2' into feature/mvvm-tasknotifier
Sergio0694 Sep 4, 2020
97ab1d8
Removed unnecessary using directives
Sergio0694 Sep 4, 2020
dd8c7b4
Bug fixes and minor optimization to ObservableValidator
Sergio0694 Sep 4, 2020
9682897
Improved support for INotifyDataErrorInfo.GetErrors
Sergio0694 Sep 4, 2020
0a7df90
Added tests for ObservableValidator
Sergio0694 Sep 4, 2020
c5cbb8c
Added support for entity-level errors
Sergio0694 Sep 4, 2020
4c7b2cf
Suppressed false positive nullability warning
Sergio0694 Sep 4, 2020
251a2e3
Merge branch 'master' into feature/mvvm-preview2
Sergio0694 Sep 4, 2020
5aafde6
Added bool return value to ValidateProperty
Sergio0694 Sep 5, 2020
15152c9
Merge pull request #26 from Sergio0694/feature/mvvm-tasknotifier
Sergio0694 Sep 10, 2020
be109be
Merge branch 'master' into feature/mvvm-preview2
michael-hawker Sep 10, 2020
77ed6e8
Removed unnecessary List<T> allocation
Sergio0694 Sep 11, 2020
e57ba22
Merge branch 'master' into feature/mvvm-preview2
Sergio0694 Sep 15, 2020
28b1977
Code refactoring in ObservableValidator
Sergio0694 Sep 24, 2020
e7a4824
Removed tracking field for HasErrors
Sergio0694 Sep 24, 2020
93018fa
Merge branch 'master' into feature/mvvm-preview2
Sergio0694 Sep 24, 2020
c5a5d5d
Fixed build error due to StyleCop
Sergio0694 Sep 24, 2020
fec4b22
Code refactoring (not a fan of StyleCop here)
Sergio0694 Sep 24, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
316 changes: 212 additions & 104 deletions Microsoft.Toolkit.Mvvm/ComponentModel/ObservableObject.cs

Large diffs are not rendered by default.

47 changes: 33 additions & 14 deletions Microsoft.Toolkit.Mvvm/ComponentModel/ObservableRecipient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Mvvm.Messaging;
using Microsoft.Toolkit.Mvvm.Messaging.Messages;
Expand Down Expand Up @@ -204,7 +203,14 @@ protected bool SetProperty<T>(ref T field, T newValue, IEqualityComparer<T> comp
/// </remarks>
protected bool SetProperty<T>(T oldValue, T newValue, Action<T> callback, bool broadcast, [CallerMemberName] string? propertyName = null)
{
return SetProperty(oldValue, newValue, EqualityComparer<T>.Default, callback, broadcast, propertyName);
bool propertyChanged = SetProperty(oldValue, newValue, callback, propertyName);

if (propertyChanged && broadcast)
{
Broadcast(oldValue, newValue, propertyName);
}

return propertyChanged;
}

/// <summary>
Expand Down Expand Up @@ -237,40 +243,53 @@ protected bool SetProperty<T>(T oldValue, T newValue, IEqualityComparer<T> compa
/// Compares the current and new values for a given nested property. If the value has changed,
/// raises the <see cref="ObservableObject.PropertyChanging"/> event, updates the property and then raises the
/// <see cref="ObservableObject.PropertyChanged"/> event. The behavior mirrors that of
/// <see cref="ObservableObject.SetProperty{T}(Expression{Func{T}},T,string)"/>, with the difference being that this
/// <see cref="ObservableObject.SetProperty{TModel,T}(T,T,TModel,Action{TModel,T},string)"/>, with the difference being that this
/// method is used to relay properties from a wrapped model in the current instance. For more info, see the docs for
/// <see cref="ObservableObject.SetProperty{T}(Expression{Func{T}},T,string)"/>.
/// <see cref="ObservableObject.SetProperty{TModel,T}(T,T,TModel,Action{TModel,T},string)"/>.
/// </summary>
/// <typeparam name="T">The type of property to set.</typeparam>
/// <param name="propertyExpression">An <see cref="Expression{TDelegate}"/> returning the property to update.</param>
/// <typeparam name="TModel">The type of model whose property (or field) to set.</typeparam>
/// <typeparam name="T">The type of property (or field) to set.</typeparam>
/// <param name="oldValue">The current property value.</param>
/// <param name="newValue">The property's value after the change occurred.</param>
/// <param name="model">The model </param>
/// <param name="callback">The callback to invoke to set the target property value, if a change has occurred.</param>
/// <param name="broadcast">If <see langword="true"/>, <see cref="Broadcast{T}"/> will also be invoked.</param>
/// <param name="propertyName">(optional) The name of the property that changed.</param>
/// <returns><see langword="true"/> if the property was changed, <see langword="false"/> otherwise.</returns>
protected bool SetProperty<T>(Expression<Func<T>> propertyExpression, T newValue, bool broadcast, [CallerMemberName] string? propertyName = null)
protected bool SetProperty<TModel, T>(T oldValue, T newValue, TModel model, Action<TModel, T> callback, bool broadcast, [CallerMemberName] string? propertyName = null)
{
return SetProperty(propertyExpression, newValue, EqualityComparer<T>.Default, broadcast, propertyName);
bool propertyChanged = SetProperty(oldValue, newValue, model, callback, propertyName);

if (propertyChanged && broadcast)
{
Broadcast(oldValue, newValue, propertyName);
}

return propertyChanged;
}

/// <summary>
/// Compares the current and new values for a given nested property. If the value has changed,
/// raises the <see cref="ObservableObject.PropertyChanging"/> event, updates the property and then raises the
/// <see cref="ObservableObject.PropertyChanged"/> event. The behavior mirrors that of
/// <see cref="ObservableObject.SetProperty{T}(Expression{Func{T}},T,IEqualityComparer{T},string)"/>,
/// <see cref="ObservableObject.SetProperty{TModel,T}(T,T,IEqualityComparer{T},TModel,Action{TModel,T},string)"/>,
/// with the difference being that this method is used to relay properties from a wrapped model in the
/// current instance. For more info, see the docs for
/// <see cref="ObservableObject.SetProperty{T}(Expression{Func{T}},T,IEqualityComparer{T},string)"/>.
/// <see cref="ObservableObject.SetProperty{TModel,T}(T,T,IEqualityComparer{T},TModel,Action{TModel,T},string)"/>.
/// </summary>
/// <typeparam name="T">The type of property to set.</typeparam>
/// <param name="propertyExpression">An <see cref="Expression{TDelegate}"/> returning the property to update.</param>
/// <typeparam name="TModel">The type of model whose property (or field) to set.</typeparam>
/// <typeparam name="T">The type of property (or field) to set.</typeparam>
/// <param name="oldValue">The current property value.</param>
/// <param name="newValue">The property's value after the change occurred.</param>
/// <param name="comparer">The <see cref="IEqualityComparer{T}"/> instance to use to compare the input values.</param>
/// <param name="model">The model </param>
/// <param name="callback">The callback to invoke to set the target property value, if a change has occurred.</param>
/// <param name="broadcast">If <see langword="true"/>, <see cref="Broadcast{T}"/> will also be invoked.</param>
/// <param name="propertyName">(optional) The name of the property that changed.</param>
/// <returns><see langword="true"/> if the property was changed, <see langword="false"/> otherwise.</returns>
protected bool SetProperty<T>(Expression<Func<T>> propertyExpression, T newValue, IEqualityComparer<T> comparer, bool broadcast, [CallerMemberName] string? propertyName = null)
protected bool SetProperty<TModel, T>(T oldValue, T newValue, IEqualityComparer<T> comparer, TModel model, Action<TModel, T> callback, bool broadcast, [CallerMemberName] string? propertyName = null)
{
bool propertyChanged = SetProperty(propertyExpression, newValue, comparer, out T oldValue, propertyName);
bool propertyChanged = SetProperty(oldValue, newValue, comparer, model, callback, propertyName);

if (propertyChanged && broadcast)
{
Expand Down
Loading