Выполнение методов ViewModel из Xamarin Forms Pages легко, но как можно вызывать методы страницы внутри ViewModels?

В Xamarin Forms, если вы привязываете команды ViewModel к кнопкам страницы, вся логика действия нажатия кнопки выполняется в ViewModel. Проблема в том, что ViewModel не имеет доступа к элементам управления Xamarin Forms, и поэтому трудно получить доступ к функциям Views из вашей ViewModel. Делегаты обычно не используются, поэтому я надеюсь, что эта статья добавит еще один инструмент в ваш арсенал, который вы можете использовать для решения ваших задач кодирования. Обратите внимание, что делегаты действия могут использоваться для всех платформ пользовательского интерфейса, использующих C #.

Пример использования: сосредоточить внимание на записи

Давайте рассмотрим сценарий, в котором у нас есть пароль Entry и логин Button для входа Page. Наше требование состоит в том, что если пароль неверен, мы хотим, чтобы ввод пароля автоматически находился в фокусе клавиатуры. Как правило, действительность пароля определяется через ViewModel с использованием вашего уровня служб, и этот класс отвечает за навигацию, если пароль правильный. Но если пароль неверен и вы хотите, чтобы пользовательский интерфейс отреагировал на эту ошибку, будет сложно сделать это традиционными средствами.

Привет Action Invoke

Теперь мы можем создать событие в ViewModel и соответствующий обработчик событий в Page. Таким образом, каждый раз, когда это событие вызывается где-нибудь в ViewModel, этот метод обработчика событий автоматически вызывается на странице.

ViewModel изменения

Как вы можете видеть в этом образце, все, что вам нужно, когда сервисы определяют, что логин не удался и вы хотите, чтобы ввод пароля получил фокус, - это две строки кода в вашей ViewModel:
объявление события public Action<bool> OnLoginFailed { get; set; }, а затем просто выполнив thisOnLoginFailed?.Invoke(true);.

Изменения страницы

На странице вы просто назначаете обработчик событий для выполнения действия:

ViewModel.OnLoginFailed = ((obj) =>
{
    PasswordEntry.Focus();
});

Обратите внимание, что объявление Action имеет тип bool, поэтому, когда мы вызываем его, мы должны передать значение соответствующего типа. Затем в обработчике событий страницы вы можете дополнительно получить доступ к этому конкретному значению (obj).

При использовании событий, чтобы избежать утечек памяти, вы можете попробовать WeakEventManager в Xamarin Community Toolkit. Если вы используете MvvmCross, вы можете использовать больше MvxInteraction, реализованное аналогичным образом. Behaviors - официальный способ реализации этой функциональности. Как предлагает Адам, вы можете использовать центр обмена сообщениями, но я думаю, что в этом нет необходимости. Если у вас есть какие-либо вопросы или мысли, не стесняйтесь обращаться каждый ко мне здесь. Вам нравится наша работа? Поддержите нас, следя за нами в социальных сетях и подписываясь на последние обновления здесь. Вы также можете узнать больше о Типе действий делегатов в C # здесь.