我正在尝试在WPF中实现相当特定的目标。我需要创建一个可验证的控件,该控件将被绑定到像这样的通用类的对象上
public interface IVerifiable
{
bool Verified { get; set; }
}
public class VerifiableProperty<T> : INotifyPropertyChanged, IVerifiable
{
private T _value;
private bool _verified;
public T Value
{
get => _value;
set
{
if (Equals(value, _value)) return;
_value = value;
OnPropertyChanged();
}
}
public bool Verified
{
get => _verified;
set
{
if (value == _verified) return;
_verified = value;
OnPropertyChanged();
}
}
}
我以此方式绑定控件
<TextBox Text="{Binding Path=Number.Value}" att:VerifiableControl.Verified="{Binding Path=Number.Verified}"
BorderBrush="{Binding Path=(att:VerifiableControl.Verified), Mode=OneWay,
Converter={StaticResource BackColorVerifiedConverter}}">
<inter:Interaction.Triggers>
<inter:EventTrigger EventName="LostFocus">
<inter:InvokeCommandAction Command="{Binding Path=DataContext.VerifyCurrentFieldCommand, ElementName=Root}"
CommandParameter="{Binding Path=Number}"/>
</inter:EventTrigger>
</inter:Interaction.Triggers>
</TextBox>
Verifiable属性对象的通用值绑定到文本(如果使用DatePicker等,则绑定到SelectedDate等),边框颜色通过转换器绑定到标志“ Verified”,并且还将“ FocusLost”事件的交互触发器绑定到ViewModel命令,将相应属性对象的“已验证”标志设置为true。
我真的不喜欢这样的想法,我必须在几乎没有任何更改的情况下多次粘贴此块。我知道,我无法在样式中添加触发触发器,也找不到另一种方式来制作某种短模式。 因此,是否有办法为此xaml代码创建某种短模式,以便我可以自定义要绑定的属性名称?或者,也许您可以为我想要实现的目标建议另一种方法?
答案 0 :(得分:1)
使用一些附加属性,并将其附加到LostFocus事件。
public static class VerifiableBehaviour
{
public static bool GetVerified(UIElement obj) => (bool)obj.GetValue(VerifiedProperty);
public static void SetVerified(DependencyObject obj, bool value) => obj.SetValue(VerifiedProperty, value);
public static readonly DependencyProperty VerifiedProperty = DependencyProperty.RegisterAttached(
"Verified", typeof(bool), typeof(VerifiableBehaviour),
new FrameworkPropertyMetadata(false)
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
});
public static bool GetTracking(UIElement obj) => (bool)obj.GetValue(TrackingProperty);
public static void SetTracking(UIElement obj, bool value) => obj.SetValue(TrackingProperty, value);
public static readonly DependencyProperty TrackingProperty = DependencyProperty.RegisterAttached(
"Tracking", typeof(bool), typeof(VerifiableBehaviour),
new PropertyMetadata(false, Tracking_PropertyChanged));
private static void Tracking_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UIElement element = d as UIElement;
if ((bool)e.NewValue)
element.LostFocus += Element_LostFocus;
else
element.LostFocus -= Element_LostFocus;
}
private static void Element_LostFocus(object sender, RoutedEventArgs e)
{
UIElement element = sender as UIElement;
SetVerified(element, true);
}
}
并将其绑定到您的控件
<StackPanel>
<StackPanel.Resources>
<DataTemplate x:Key="VerifiableText">
<StackPanel>
<TextBox b:VerifiableBehaviour.Tracking="True"
b:VerifiableBehaviour.Verified="{Binding Verified}"
Text="{Binding Value}"/>
<TextBlock>(Verified: <Run Text="{Binding Verified}"/>)</TextBlock>
</StackPanel>
</DataTemplate>
</StackPanel.Resources>
<TextBlock Text="MyProperty1"/>
<ContentControl ContentTemplate="{StaticResource VerifiableText}"
Content="{Binding MyProperty1}" IsTabStop="False"/>
<Separator/>
<TextBlock Text="MyProperty2"/>
<ContentControl ContentTemplate="{StaticResource VerifiableText}"
Content="{Binding MyProperty2}" IsTabStop="False"/>
<Separator/>
<TextBlock Text="MyProperty3"/>
<ContentControl ContentTemplate="{StaticResource VerifiableText}"
Content="{Binding MyProperty3}" IsTabStop="False"/>
<Separator/>
<TextBlock Text="MyProperty4"/>
<ContentControl ContentTemplate="{StaticResource VerifiableText}"
Content="{Binding MyProperty4}" IsTabStop="False"/>
<Separator/>
</StackPanel>