私はソースコードを調べましたが、BindingExpressionBase
それ自体が。というプロパティを通じてこれを認識していますNeedsUpdate
。ただし、このプロパティは内部的なものであるため、リフレクションを使用して取得する必要があります。
ただし、このプロパティを簡単な方法で監視することはできません。したがって、私の見方では、両方のイベントを使用し、いつ変更されたかを知る必要がTextChanged
ありSourceUpdated
ますNeedsUpdate
。
更新
これを行う添付の動作を作成しました。これを使用して、任意ので保留中の更新を監視できますDependencyProperty
。trueに設定する必要があることに注意してくださいNotifyOnSourceUpdated
。
ここに小さなサンプルプロジェクトをアップロードしました:PendingUpdateExample.zip
例
<TextBox Text="{Binding ElementName=textBoxSource,
Path=Text,
NotifyOnSourceUpdated=True,
UpdateSourceTrigger=PropertyChanged,
Delay=1000}"
ab:UpdatePendingBehavior.MonitorPendingUpdates="{x:Static TextBox.TextProperty}">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="ab:UpdatePendingBehavior.HasPendingUpdates"
Value="True">
<Setter Property="Background" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
UpdatePendingBehavior
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
}
別の方法はMultiBinding
、ソースとターゲットの両方にバインドし、コンバーターでそれらの値を比較するを使用することです。Background
次に、を変更できますStyle
。これは、値を変換しないことを前提としています。2つの例TextBoxes
<TextBox Text="{Binding ElementName=textBoxSource,
Path=Text,
UpdateSourceTrigger=PropertyChanged,
Delay=2000}">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Value="False">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource IsTextEqualConverter}">
<Binding RelativeSource="{RelativeSource Self}"
Path="Text"/>
<Binding ElementName="textBoxSource" Path="Text"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<TextBox Name="textBoxSource"/>
IsTextEqualConverter
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();
}
}