【问题标题】:Repeatable pattern in WPFWPF 中的可重复模式
【发布时间】:2018-11-12 03:24:26
【问题描述】:

我正在尝试在 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),边框颜色通过转换器绑定到标记“已验证”,并且我将“FocusLost”事件的交互触发器绑定到 ViewModel 命令将相应属性对象的“已验证”标志设置为 true。

我真的不喜欢我必须多次复制粘贴此块而几乎没有更改的想法。我知道,我不能把交互触发器放在风格上,我也找不到另一种方法来为此制作某种短模式。 那么,有没有办法为这个 xaml 代码创建某种短模式,我可以自定义要绑定的属性名称?或者,也许您可​​以针对我想要实现的目标提出另一种方法?

【问题讨论】:

    标签: c# wpf xaml data-binding


    【解决方案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>
    

    【讨论】:

    • 明白了,谢谢。没有为此尝试数据模板。所以,我想,我需要为我想使用的每种类型的控件提供一个数据模板
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 2014-01-06
    • 2015-11-01
    • 1970-01-01
    相关资源
    最近更新 更多