Привязка к событию через Interaction EventTrigger завершается позже чем возникает само событие

Допустим есть ViewModel с двумя свойствами, и командами обрабатывающими загрузку формы и изменение текста:

public class MyViewModel : ViewModelBase
{
    public string TestString { get; set; } = "";

    public string TestString2 { get; set; } = "";

    private RelayCommand<RoutedEventArgs> _loadedCommand;

    public RelayCommand<RoutedEventArgs> LoadedCommand =>
        _loadedCommand ??= new RelayCommand<RoutedEventArgs>(Loaded);

    private RelayCommand _textChangedCommand;

    public RelayCommand TextChangedCommand =>
        _textChangedCommand ??= new RelayCommand(TextChanged);


    private void Loaded(RoutedEventArgs e)
    {
        TestString = "Loaded";
    }

    private void TextChanged()
    {
        TestString2 = "Modified";
    }
}

XAML формы:

<UserControl x:Class="WpfApp.Views.MyView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApp.Views"
             xmlns:viewmodel="clr-namespace:WpfApp.ViewModels"
             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
             d:DataContext="{d:DesignInstance Type=viewmodel:MyViewModel}"
             mc:Ignorable="d" 
             d:DesignHeight="800" d:DesignWidth="1200">

    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding LoadedCommand}" PassEventArgsToCommand="True"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        
        <TextBox Text="{Binding TestString}">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="TextChanged">
                    <i:InvokeCommandAction Command="{Binding TextChangedCommand}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBox>

        <TextBlock Text="{Binding TestString2}" Grid.Column="1"/>
    </Grid>
</UserControl>

У TextBlock должен поменяться текст на "Modified", но этого не происходит потому что привязка устанавливается слишком долго, в итоге событие TextChanged возникает раньше чем завершится привязка к нему.

Надпись "Modified" появляется если добавить задержку:

private async void Loaded(RoutedEventArgs e)
{
    await Task.Delay(1000);
    TestString = "Loaded";
}

Есть ли красивый способ решить эту проблему?


Ответы (1 шт):

Автор решения: aepot

Триггер для TextChangedCommand - в чём смысл? Есть же привязка.

<TextBox Text="{Binding TestString}">

Берём свойство

private string _testString = "";

public string TestString
{
   get => _testString;
   set
   {
       _testString = value;
       OnPropertyChanged();
       TextChangedCommand.Execute();
   }
};

А триггер из XAML выбрасываем.

→ Ссылка