Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I had a look through the source code and the <code>BindingExpressionBase</code> itself is aware of this through a property called <code>NeedsUpdate</code>. But this property is internal so you would have to use reflection to get it.</p> <p>However, you won't be able to monitor this property in any easy way. So the way I see it, you would need to use both of the events <code>TextChanged</code> and <code>SourceUpdated</code> to know when <code>NeedsUpdate</code> might have changed.</p> <p><strong>Update</strong><br> I created an attached behavior that does this, it can be used to monitor pending updates on any <code>DependencyProperty</code>. <em>Note that <code>NotifyOnSourceUpdated</code> must be set to true</em>.</p> <p>Uploaded a small sample project here: <a href="http://dl.dropbox.com/u/39657172/PendingUpdateExample.zip">PendingUpdateExample.zip</a></p> <p><em>Example</em></p> <pre><code>&lt;TextBox Text="{Binding ElementName=textBoxSource, Path=Text, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, Delay=1000}" ab:UpdatePendingBehavior.MonitorPendingUpdates="{x:Static TextBox.TextProperty}"&gt; &lt;TextBox.Style&gt; &lt;Style TargetType="TextBox"&gt; &lt;Style.Triggers&gt; &lt;Trigger Property="ab:UpdatePendingBehavior.HasPendingUpdates" Value="True"&gt; &lt;Setter Property="Background" Value="Green"/&gt; &lt;/Trigger&gt; &lt;/Style.Triggers&gt; &lt;/Style&gt; &lt;/TextBox.Style&gt; &lt;/TextBox&gt; </code></pre> <p><strong>UpdatePendingBehavior</strong></p> <pre><code>public class UpdatePendingBehavior { #region MonitorPendingUpdates public static DependencyProperty MonitorPendingUpdatesProperty = DependencyProperty.RegisterAttached("MonitorPendingUpdates", typeof(DependencyProperty), typeof(UpdatePendingBehavior), new UIPropertyMetadata(null, MonitorPendingUpdatesChanged)); public static DependencyProperty GetMonitorPendingUpdates(FrameworkElement obj) { return (DependencyProperty)obj.GetValue(MonitorPendingUpdatesProperty); } public static void SetMonitorPendingUpdates(FrameworkElement obj, DependencyProperty value) { obj.SetValue(MonitorPendingUpdatesProperty, value); } public static void MonitorPendingUpdatesChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) { DependencyProperty property = e.NewValue as DependencyProperty; if (property != null) { FrameworkElement element = target as FrameworkElement; element.SourceUpdated += elementProperty_SourceUpdated; if (element.IsLoaded == true) { SubscribeToChanges(element, property); } element.Loaded += delegate { SubscribeToChanges(element, property); }; element.Unloaded += delegate { UnsubscribeToChanges(element, property); }; } } private static void SubscribeToChanges(FrameworkElement element, DependencyProperty property) { DependencyPropertyDescriptor propertyDescriptor = DependencyPropertyDescriptor.FromProperty(property, element.GetType()); propertyDescriptor.AddValueChanged(element, elementProperty_TargetUpdated); } private static void UnsubscribeToChanges(FrameworkElement element, DependencyProperty property) { DependencyPropertyDescriptor propertyDescriptor = DependencyPropertyDescriptor.FromProperty(property, element.GetType()); propertyDescriptor.RemoveValueChanged(element, elementProperty_TargetUpdated); } private static void elementProperty_TargetUpdated(object sender, EventArgs e) { FrameworkElement element = sender as FrameworkElement; UpdatePendingChanges(element); } private static void elementProperty_SourceUpdated(object sender, DataTransferEventArgs e) { FrameworkElement element = sender as FrameworkElement; if (e.Property == GetMonitorPendingUpdates(element)) { UpdatePendingChanges(element); } } private static void UpdatePendingChanges(FrameworkElement element) { BindingExpressionBase beb = BindingOperations.GetBindingExpressionBase(element, GetMonitorPendingUpdates(element)); BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic; PropertyInfo needsUpdateProperty = beb.GetType().GetProperty("NeedsUpdate", bindingFlags); SetHasPendingUpdates(element, (bool)needsUpdateProperty.GetValue(beb)); } #endregion // MonitorPendingUpdates #region HasPendingUpdates public static DependencyProperty HasPendingUpdatesProperty = DependencyProperty.RegisterAttached("HasPendingUpdates", typeof(bool), typeof(UpdatePendingBehavior), new UIPropertyMetadata(false)); public static bool GetHasPendingUpdates(FrameworkElement obj) { return (bool)obj.GetValue(HasPendingUpdatesProperty); } public static void SetHasPendingUpdates(FrameworkElement obj, bool value) { obj.SetValue(HasPendingUpdatesProperty, value); } #endregion // HasPendingUpdates } </code></pre> <hr> <p>Another way could be to use a <code>MultiBinding</code> that binds both to the source and the target and compares their values in a converter. Then you could change the <code>Background</code> in the <code>Style</code>. <em>This assumes that you don't convert the value</em>. Example with two <code>TextBoxes</code></p> <pre><code>&lt;TextBox Text="{Binding ElementName=textBoxSource, Path=Text, UpdateSourceTrigger=PropertyChanged, Delay=2000}"&gt; &lt;TextBox.Style&gt; &lt;Style TargetType="TextBox"&gt; &lt;Style.Triggers&gt; &lt;DataTrigger Value="False"&gt; &lt;DataTrigger.Binding&gt; &lt;MultiBinding Converter="{StaticResource IsTextEqualConverter}"&gt; &lt;Binding RelativeSource="{RelativeSource Self}" Path="Text"/&gt; &lt;Binding ElementName="textBoxSource" Path="Text"/&gt; &lt;/MultiBinding&gt; &lt;/DataTrigger.Binding&gt; &lt;Setter Property="Background" Value="Green"/&gt; &lt;/DataTrigger&gt; &lt;/Style.Triggers&gt; &lt;/Style&gt; &lt;/TextBox.Style&gt; &lt;/TextBox&gt; &lt;TextBox Name="textBoxSource"/&gt; </code></pre> <p><em>IsTextEqualConverter</em></p> <pre><code>public class IsTextEqualConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { return values[0].ToString() == values[1].ToString(); } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotSupportedException(); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload