Как управлять триггером обновления в односторонней привязке данных в wpf?

При использовании привязки данных в WPF, если вы установите для свойства Mode значение TwoWay, вы можете контролировать момент, когда свойство источника будет обновлено, установив свойство UpdateSourceTrigger. Этот сценарий возможен для потока обновлений target -> source. Но как вы можете контролировать то же самое для источника -> целевого потока обновлений? Я не могу найти эквивалентную недвижимость.

Например, допустим, у меня есть два текстовых поля в моем окне, и я хочу связать текстовые свойства обоих текстовых полей. XAML может выглядеть так:

        <TextBox
            Name="txt1"
            Text="{Binding ElementName=txt2, Path=Text, Mode=TwoWay,
            UpdateSourceTrigger=LostFocus}"
            />
        <TextBox
            Name="txt2"
            />

Когда пользователь вводит текст в txt1 TextBox, свойство Text txt2 Textbox будет обновляться по мере изменения свойства Text, просто если бы я реализовал событие TextChanged на txt1.

Однако, когда пользователь вводит текст в txt2 TextBox, свойство Text для txt1 Textbox будет обновлено после того, как txt2 TextBox потеряет фокус, потому что для свойства UpdateSourceTrigger установлено значение LostFocus, просто если бы я реализовал событие LostFocus.

Есть ли возможность в привязке данных WPF обновлять целевое свойство после того, как элемент управления исходным свойством теряет фокус? В нашем примере: что нужно сделать с приведенным выше кодом XAML, чтобы свойство Text txt2 TextBox обновлялось только после того, как txt1 TextBox потерял фокус, а не после изменения его свойства Text?

Спасибо!


person Bogdan    schedule 12.03.2015    source источник


Ответы (2)


Почему бы не определить две привязки? Это работает для меня:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBox Name="txt1" Margin="4" 
                 Text="{Binding ElementName=txt2, Path=Text, Mode=OneWay}" />
        <TextBox Name="txt2" Margin="4" 
                 Text="{Binding ElementName=txt1, Path=Text, Mode=OneWay}" />
    </StackPanel>
</Window>
person Rico Suter    schedule 12.03.2015

Механизм UpdateSourceTrigger связан с неявной природой элемента управления WPF. Таким образом, вы можете решить, когда обновлять источник. С другой стороны, источником может быть UIElement, но это может быть и другой объект. Действительно, объект, являющийся источником привязки, может уведомлять об изменениях привязки, реализуя INotifyPropertyChanged. С помощью этого интерфейса объект замечает свои изменения каждый раз при изменении свойства.

Поэтому, если вам нужен своего рода «UpdateTargetTrigger», вы должны реализовать его в элементе управления. Например, вы можете расширить элемент управления TextBox следующим образом:

public class ExtTextBox : TextBox, INotifyPropertyChanged
{
    private event PropertyChangedEventHandler propertyChanged;
    private string textOnLostFocus;

    public event PropertyChangedEventHandler PropertyChanged
    {
        add
        {
            propertyChanged += value;
        }
        remove
        {
            propertyChanged -= value;
        }
    }

    private void OnPropertyChanged(string propertyName)
    {
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected override void OnLostFocus(RoutedEventArgs e)
    {
        base.OnLostFocus(e);
        SetTextOnLostFocus(Text, false);
    }

    private void SetTextOnLostFocus(string text, bool updateText)
    {
        if (StringComparer.Ordinal.Compare(textOnLostFocus, text) != 0)
        {
            textOnLostFocus = text;
            if (updateText)
            {
                Text = text;
            }

            OnPropertyChanged("TextOnLostFocus");
        }
    }

    public string TextOnLostFocus
    {
        get
        {
            return textOnLostFocus;
        }
        set
        {
            SetTextOnLostFocus(Text, true);
        }
    }
}

Я использую TextOnLostFocus в качестве поддержки, чтобы уведомлять об изменениях только в событии LostFocus. Поэтому ваш XAML будет:

<TextBox Name="txt1" Text="{Binding ElementName=txt2, Path=TextOnLostFocus, Mode=TwoWay,
                                    UpdateSourceTrigger=LostFocus}" Margin="3" />
<local:ExtTextBox x:Name="txt2" Margin="3" />

Надеюсь, это поможет тебе.

person Il Vic    schedule 13.03.2015