Повторяемый шаблон в WPF - PullRequest
0 голосов
/ 12 ноября 2018

Я пытаюсь достичь довольно конкретной вещи в 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 привязывается к тексту (или SelectedDate в случае DatePicker и т. Д.), Цвет границы привязывается к флагу «Verified» через конвертер, а также я связываю триггер взаимодействия для события «FocusLost» с командой ViewModel, которая просто установите флаг «Проверено» соответствующего объекта свойства в значение true.

Мне действительно не нравится идея, что я должен копировать этот блок много раз с небольшими изменениями. Я знаю, я не могу поставить триггер стиля в стиле, и я также не мог найти другой способ сделать какой-то короткий образец для этого. Итак, есть ли способ создать какой-то короткий шаблон для этого кода XAML, где я мог бы настроить имя свойства для привязки? Или, может быть, вы могли бы предложить другой подход к тому, чего я хочу достичь?

1 Ответ

0 голосов
/ 12 ноября 2018

Используйте некоторые вложенные свойства и прикрепите их к событию 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...