Есть кнопка триггера UpdateSource на привязку элемента управления без кода позади? - PullRequest
0 голосов
/ 08 ноября 2019

Скажем, у меня есть два поля, которые содержат значения, и я хочу, чтобы ViewModel обновлялся только при нажатии кнопки сохранения.

Исходя из моего исследования, два основных способа получения кнопки триггера для обновления полей - это иметь codebehind, вызывающий updateSource () для выражений привязки, или добавить сложность ViewModel для обработки промежуточных значений.

Неужели нет способа вызвать updateSource, используя только XAML?

1 Ответ

0 голосов
/ 08 ноября 2019

Нет встроенного способа запуска обновления из XAML, но вы можете создать свой собственный. Например, вы можете использовать инфраструктуру, настроенную Microsoft.Xaml.Behaviors.Wpf .

Сначала создайте действие, которое вы можете выполнить в ответ на триггер из XAML. Это действие настраивается парой Target / PropertyName. Учитывая эту информацию, Action знает, какое свойство для какого элемента обновлять (в вашем случае свойство Text в вашем TextBox). Эти свойства должны быть установлены в XAML (см. Ниже).

Invoke-метод вызывается соответствующим триггером, объявленным в XAML (в вашем случае, событие Button.Click, опять же, см. Ниже), выне вызывайте его самостоятельно в коде.

    public class UpdateBindingAction : TriggerAction<FrameworkElement>
    {
        public FrameworkElement Target
        {
            get { return (FrameworkElement)GetValue(TargetProperty); }
            set { SetValue(TargetProperty, value); }
        }

        public static readonly DependencyProperty TargetProperty =
            DependencyProperty.Register(nameof(Target), typeof(FrameworkElement), typeof(UpdateBindingAction), new PropertyMetadata(null));


        public string PropertyName
        {
            get { return (string)GetValue(PropertyNameProperty); }
            set { SetValue(PropertyNameProperty, value); }
        }

        public static readonly DependencyProperty PropertyNameProperty =
            DependencyProperty.Register("PropertyName", typeof(string), typeof(UpdateBindingAction), new PropertyMetadata(null));


        protected override void Invoke(object parameter)
        {
            if (Target == null)
                return;

            if (string.IsNullOrEmpty(PropertyName))
                return;

            var propertyDescriptor = DependencyPropertyDescriptor.FromName(PropertyName, Target.GetType(), Target.GetType());
            if (propertyDescriptor == null)
                return;

            Target.GetBindingExpression(propertyDescriptor.DependencyProperty).UpdateSource();
        }
    }

Затем создайте привязку в XAML, которая не обновляется автоматически

<TextBox x:Name="txt1" Width="200" Text="{Binding String1, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />
<TextBox x:Name="txt2" Width="200" Text="{Binding String2, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />

Наконец, создайте кнопку, которая содержит EventTrigger длясобытие Click, которое выполняет действие UpdateSourceAction. Пространство имен "b:" - xmlns:b="http://schemas.microsoft.com/xaml/behaviors" (из Microsoft.Xaml.Behaviors.Wpf), пространство имен "local:" - это то, куда вы помещаете действие UpdateBindingAction.

        <Button Margin="10" Content="Update">
            <b:Interaction.Triggers>
                <b:EventTrigger EventName="Click">
                    <local:UpdateBindingAction Target="{Binding ElementName=txt1}" PropertyName="Text" />
                    <local:UpdateBindingAction Target="{Binding ElementName=txt2}" PropertyName="Text" />
                    <!-- ... -->
                </b:EventTrigger>
            </b:Interaction.Triggers>
        </Button>

Существует несколько общих встроенныхв триггерах (EventTrigger, PropertyChangedTrigger, ...) и действиях (ChangePropertyAction, CallMethodAction, ...), но очень возможно реализовать свои собственные дополнения, такие как этот.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...