这是一种通过附加事件执行此操作的方法。它只能为每个控件处理一个属性的引发更改事件。要针对多个属性的值更改引发事件,您需要一个附加属性,该属性是一些具有属性名称和event 的对象的集合,这样编写起来会更复杂。这实际上只是演示了这个概念,但是对于您现在面临的特定问题已经足够了。
public static class PropertyChange
{
public static readonly RoutedEvent PropertyChangeEvent =
EventManager.RegisterRoutedEvent("PropertyChangeEvent", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(PropertyChange));
public static void AddPropertyChangeEventHandler(DependencyObject d, RoutedEventHandler handler)
{
var uie = d as UIElement;
if (uie != null)
{
uie.AddHandler(PropertyChange.PropertyChangeEvent, handler);
}
}
public static void RemovePropertyChangeEventHandler(DependencyObject d, RoutedEventHandler handler)
{
var uie = d as UIElement;
if (uie != null)
{
uie.RemoveHandler(PropertyChange.PropertyChangeEvent, handler);
}
}
#region PropertyChange.PropertyName Attached Property
public static String GetPropertyName(UIElement obj)
{
return (String)obj.GetValue(PropertyNameProperty);
}
public static void SetPropertyName(UIElement obj, String value)
{
obj.SetValue(PropertyNameProperty, value);
}
public static readonly DependencyProperty PropertyNameProperty =
DependencyProperty.RegisterAttached("PropertyName", typeof(String), typeof(PropertyChange),
new PropertyMetadata(null, PropertyName_PropertyChanged));
private static void PropertyName_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = d as UIElement;
var oldProperty = e.OldValue as String;
var newProperty = e.NewValue as String;
if (oldProperty != null)
{
var dpd = DependencyPropertyDescriptor.FromName(oldProperty, d.GetType(), d.GetType());
dpd.RemoveValueChanged(d, PropertyChangedHandler);
}
if (newProperty != null)
{
var dpd = DependencyPropertyDescriptor.FromName(newProperty, d.GetType(), d.GetType());
dpd.AddValueChanged(d, PropertyChangedHandler);
}
}
private static void PropertyChangedHandler(object component, EventArgs args)
{
var uie = component as UIElement;
uie.RaiseEvent(new RoutedEventArgs(PropertyChange.PropertyChangeEvent, uie));
}
#endregion PropertyChange.PropertyName Attached Property
}
演示
XAML
<TextBox
Width="100"
x:Name="TestTextBox"
Text="Blah blah blah"
local:PropertyChange.PropertyName="Background"
local:PropertyChange.PropertyChangeEvent="TestTextBox_PropertyChangeEvent"
>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
后面的代码
private void TestTextBox_PropertyChangeEvent(object sender, RoutedEventArgs e)
{
var tb = (TextBox)sender;
var x = tb.Background as SolidColorBrush;
// Instead of examining the background color, I would much prefer to look directly
// at the validation: What happens if you decide to change the error background color
// to a darker shade of red? Or a GradientBrush? A cosmetic decision like that should
// not affect program behavior.
//
// But you didn't give any clues about how your validation is implemented, so that's
// your problem not mine.
if (x != null && x.Color == Colors.Red)
{
tb.Focus();
tb.SelectAll();
}
}