diff --git a/src/Perspex.Base/PerspexObject.cs b/src/Perspex.Base/PerspexObject.cs
index 7c1317a7bc..337fbf185d 100644
--- a/src/Perspex.Base/PerspexObject.cs
+++ b/src/Perspex.Base/PerspexObject.cs
@@ -807,18 +807,33 @@ namespace Perspex
newValue,
priority);
- OnPropertyChanged(e);
- property.NotifyChanged(e);
-
- if (PropertyChanged != null)
+ if (property.Notifying != null)
{
- PropertyChanged(this, e);
+ property.Notifying(this, true);
}
- if (_inpcChanged != null)
+ try
{
- PropertyChangedEventArgs e2 = new PropertyChangedEventArgs(property.Name);
- _inpcChanged(this, e2);
+ OnPropertyChanged(e);
+ property.NotifyChanged(e);
+
+ if (PropertyChanged != null)
+ {
+ PropertyChanged(this, e);
+ }
+
+ if (_inpcChanged != null)
+ {
+ PropertyChangedEventArgs e2 = new PropertyChangedEventArgs(property.Name);
+ _inpcChanged(this, e2);
+ }
+ }
+ finally
+ {
+ if (property.Notifying != null)
+ {
+ property.Notifying(this, false);
+ }
}
}
diff --git a/src/Perspex.Base/PerspexProperty.cs b/src/Perspex.Base/PerspexProperty.cs
index 3bda662038..e44284b570 100644
--- a/src/Perspex.Base/PerspexProperty.cs
+++ b/src/Perspex.Base/PerspexProperty.cs
@@ -63,6 +63,11 @@ namespace Perspex
/// Whether the property inherits its value.
/// The default binding mode for the property.
/// A validation function.
+ ///
+ /// A method that gets called before and after the property starts being notified on an
+ /// object; the bool argument will be true before and false afterwards. This callback is
+ /// intended to support IsDataContextChanging.
+ ///
/// Whether the property is an attached property.
public PerspexProperty(
string name,
@@ -72,6 +77,7 @@ namespace Perspex
bool inherits = false,
BindingMode defaultBindingMode = BindingMode.Default,
Func validate = null,
+ Action notifying = null,
bool isAttached = false)
{
Contract.Requires(name != null);
@@ -90,6 +96,7 @@ namespace Perspex
Inherits = inherits;
DefaultBindingMode = defaultBindingMode;
IsAttached = isAttached;
+ Notifying = notifying;
_id = s_nextId++;
if (validate != null)
@@ -240,6 +247,16 @@ namespace Perspex
///
public IObservable Changed => _changed;
+ ///
+ /// The notifying callback.
+ ///
+ ///
+ /// This is a method that gets called before and after the property starts being notified
+ /// on an object; the bool argument will be true before and false afterwards. This
+ /// callback is intended to support IsDataContextChanging.
+ ///
+ public Action Notifying { get; }
+
///
/// Provides access to a property's binding via the
/// indexer.
@@ -323,13 +340,19 @@ namespace Perspex
/// Whether the property inherits its value.
/// The default binding mode for the property.
/// A validation function.
+ ///
+ /// A method that gets called before and after the property starts being notified on an
+ /// object; the bool argument will be true before and false afterwards. This callback is
+ /// intended to support IsDataContextChanging.
+ ///
/// A
public static PerspexProperty Register(
string name,
TValue defaultValue = default(TValue),
bool inherits = false,
BindingMode defaultBindingMode = BindingMode.OneWay,
- Func validate = null)
+ Func validate = null,
+ Action notifying = null)
where TOwner : PerspexObject
{
Contract.Requires(name != null);
@@ -341,6 +364,7 @@ namespace Perspex
inherits,
defaultBindingMode,
Cast(validate),
+ notifying,
false);
PerspexObject.Register(typeof(TOwner), result);
@@ -404,6 +428,7 @@ namespace Perspex
inherits,
defaultBindingMode,
validate,
+ null,
true);
PerspexObject.Register(typeof(THost), result);
@@ -440,6 +465,7 @@ namespace Perspex
inherits,
defaultBindingMode,
validate,
+ null,
true);
PerspexObject.Register(typeof(THost), result);
diff --git a/src/Perspex.Base/PerspexProperty`1.cs b/src/Perspex.Base/PerspexProperty`1.cs
index 3c81b5e91b..73ac84e102 100644
--- a/src/Perspex.Base/PerspexProperty`1.cs
+++ b/src/Perspex.Base/PerspexProperty`1.cs
@@ -20,6 +20,11 @@ namespace Perspex
/// Whether the property inherits its value.
/// The default binding mode for the property.
/// A validation function.
+ ///
+ /// A method that gets called before and after the property starts being notified on an
+ /// object; the bool argument will be true before and false afterwards. This callback is
+ /// intended to support IsDataContextChanging.
+ ///
/// Whether the property is an attached property.
public PerspexProperty(
string name,
@@ -28,6 +33,7 @@ namespace Perspex
bool inherits = false,
BindingMode defaultBindingMode = BindingMode.Default,
Func validate = null,
+ Action notifying = null,
bool isAttached = false)
: base(
name,
@@ -37,6 +43,7 @@ namespace Perspex
inherits,
defaultBindingMode,
Cast(validate),
+ notifying,
isAttached)
{
}
diff --git a/src/Perspex.Controls/Control.cs b/src/Perspex.Controls/Control.cs
index b48b4afca6..e41be6ccc3 100644
--- a/src/Perspex.Controls/Control.cs
+++ b/src/Perspex.Controls/Control.cs
@@ -32,7 +32,10 @@ namespace Perspex.Controls
/// Defines the property.
///
public static readonly PerspexProperty