DRD94 Ответов: 1

MVVM странное поведение мессенджера


Я пытаюсь передать пользователя между двумя моделями просмотра. Для этого я использую фреймворк MVVM light Messenger. Несмотря на то, что точка останова находится там, где я пытаюсь воздействовать на модель, которая передается во вторую ViewModel, некоторые текстовые блоки, привязанные к свойствам, не обновляются.

Что я уже пробовал:

Вот как я передаю "пользователя", когда кто-то нажимает кнопку входа в систему:

#region Login
private DelegateCommand _loginCommand;
public ICommand LoginCommand
{
    get
    {
        _loginCommand = new DelegateCommand(param => Login());
        return _loginCommand;
    }
}

private async void Login()
{
    var waitWindow = new PleaseWaitWindow();
    waitWindow.Show();

    if (await LoginCheck())
    {
        // TODO: Navigate to the DashboardView
        Messenger.Default.Send(new ChangePage(typeof(DashboardViewModel)));
        Messenger.Default.Send(_chosenUser);
    }

    waitWindow.Close();
}
#endregion


Вот как я подписываюсь на это сообщение и использую его содержимое:

public DashboardViewModel()
{
    Messenger.Default.Register<User>(this, OnUserReceived);
    Messenger.Default.Register<ChangePage>(this, ChangePage); // Register to Messenger to change Views hosted in ContentControl
}

private void OnUserReceived(User user)
{
    FirstName = user.FirstName; // Breakpoint is hit here with correct value
    LastName = user.LastName;
}


И два текстовых блока, которые привязаны к свойствам FirstName и LastName..:

<StackPanel VerticalAlignment="Center" Margin="5">
    <TextBlock Text="{Binding FirstName}" Foreground="White" Margin="5" FontSize="18"/>
    <TextBlock Text="{Binding LastName}" Foreground="White" FontWeight="Bold" Margin="5" FontSize="20"/>
</StackPanel>


Если я установлю точку останова, где я действую на мессенджер, то FirstName и LastName будут установлены в правильные значения. Однако текстовые блоки не обновляются,и их текст остается пустым.

Я реализовал кнопку test в DashboardView, которая просто устанавливает FirstName = "Test"; и это действительно обновляет текстовый блок, чтобы сказать текст, поэтому я не понимаю, почему передача типа пользователя и использование его имени и фамилии не работает.

РЕДАКТИРОВАТЬ:

private void OnUserReceived(User user)
{
    Application.Current.Dispatcher.Invoke(() =>
    {
        FirstName = user.FirstName;
        LastName = user.LastName;
    });
}

1 Ответов

Рейтинг:
0

TheRealSteveJudge

Такое поведение вполне нормально,
поскольку посланник находится на другой нити.

У меня тоже однажды был такой феномен.

Вы должны использовать диспетчера:

Application.Current.Dispatcher.Invoke(() =>
{
    FirstName = user.FirstName; // Breakpoint is hit here with correct value
    LastName = user.LastName;
});


DRD94

Спасибо, что уделили мне время. Я обновил свой ответ, чтобы подумать о добавлении диспетчера, однако, к сожалению, текстовые блоки все еще не обновляются, что очень расстраивает. Я даже добавил кнопку, привязанную к команде, которая устанавливает FirstName = "Test". Это действительно обновляет текстовый блок, так что я вижу только проблему с мессенджером.

TheRealSteveJudge

Без проблем.
Вы устанавливаете цвет переднего плана на "Белый".
Что произойдет, если вы установите его, например, черным?

DRD94

У меня черный фон, следовательно, белый. Я сменил его на красный, и все равно не повезло. Если я установлю кнопку на что-то вроде MessageBox.Show (FirstName);, так что после того, как FirstName должно быть установлено в переданное значение, оно просто показывает null. Мне кажется, что FirstName устанавливается там, где находится точка останова, но затем по какой-то причине снова стирается.

TheRealSteveJudge

ОК. Я подумал, что, может быть, фон тоже белый.
Что вы видите при использовании отладчика в первой строке метода OnUserReceived? Как часто происходит попадание точки останова после входа в систему?

DRD94

Теперь я совсем запутался. Точка останова задается только один раз, и имя/фамилия задаются правильно. Если я добавлю MessageBox в конец метода OnUserReceived и пройду через отладчик, то будет похоже, что ViewModel инициализируется перед представлением. Есть ли способ проверить, что представление (и его текстовые блоки) инициализируются перед ViewModel? Может быть, отправка ViewModel для изменения ViewModels все портит?

TheRealSteveJudge

Как вы строите ViewModel?

Я делаю это вот так:

общественный разделяемого класса файл MainWindow
{
публичное главное окно()
{
метод InitializeComponent();

var vm = новая модель представления();

DataContext = виртуальная машина;
}
}

DRD94

Я делаю это в XAML так: <vm:DashboardViewModel x: Key= "DashboardViewModel"/> В разделе ресурсов, а затем

    <UserControl.DataContext>
        <Binding Mode="OneWay" Source="{StaticResource DashboardViewModel}"/>
    </UserControl.DataContext>