Xamarin. Формы передачи данных между экранами с MVVM - PullRequest
0 голосов
/ 12 сентября 2018

У меня есть два экрана.

На первом из них есть две Entries и кнопка Сохранить, на втором - два Labels.

Оба имеют соответствующие привязки ViewModels.

например, 1-й XAML:

<Entry x:Name="Entry1" Text="{Binding Entry1}"/>
<Button Command="{Binding SaveCommand}" Text="Save"/>

1-я ViewModel:

class Screen1ViewModel: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    private string entry1;
    public string Entry1;
    {
        get { return entry1; }
        set
        {
            entry1= value;
            PropertyChanged(this, new PropertyChangedEventArgs("Entry1"));
        }
    }
    //similar code for Entry2

    public ICommand SaveCommand { protected set; get; }

    public Screen1ViewModel()
    {
        SaveCommand = new Command(OnSubmit);
    }

    public void OnSubmit()
    {
        //I guess here I supposed to transfer data from 1st screen to 2nd
    }

}

Есть ли простой способ получить строки из записей 1-го экрана и передать их на 2-й экранэтикетки с использованием ViewModels?

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Если вы не хотите, чтобы эти модели представления были связаны или имели отношения друг с другом, вам нужен какой-то механизм агрегатора событий или обмена сообщениями (pub-sub). Для этого Xamarin Forms поставляется со службой обмена сообщениями, которая называется Центр сообщений .

0 голосов
/ 12 сентября 2018

Я реализовал очень упрощенный пример для вас. Конечно, это не лучшая реализация, чтобы делать следующее:

((testApp.App)App.Current).MainPage.Navigation

Лучший способ реализовать навигацию - использовать службу навигации, как в следующей статье: https://mallibone.com/post/a-simple-navigation-service-for-xamarinforms

Это лучше, так как в этом случае ваша viewModel ничего не знает о страницах, она знает только строковый ключ страницы. Также легче понять код и отладить его, поскольку существует центральная точка вызова.

Существует также легкий инструментарий MVVM. В следующей статье показано, как использовать его возможности и реализовать навигацию: https://mobileprogrammerblog.wordpress.com/2017/01/21/xamarin-forms-with-mvvm-light/

Служба обмена сообщениями - это худшая вещь, которую я могу порекомендовать в отношении навигации, поскольку трудно понять код, а отладка - это настоящий беспорядок. Развязывая код, вы делаете зависимые вещи независимыми, и новые люди не могут понять, как работает код. Обмен сообщениями полезен при передаче событий из внутренних viewModels в модель представления корневой страницы или из модели представления для просмотра или на страницу, но он не подходит для задачи навигации.

Мой простой пример можно найти ниже: Код приложения:

public App()
{
   InitializeComponent();
   MainPage = new NavigationPage(new Views.Page1());
}

Page1.xaml:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    x:Class="testApp.Views.Page1"
    xmlns:local="clr-namespace:testApp.Views;assemply=testApp">
    <ContentPage.BindingContext>
        <local:Page1ViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
    <StackLayout>
        <Entry Text="{Binding TextPropertyValue}" />
        <Button Command="{Binding SaveCommand}" Text="Save"/>
            </StackLayout>
    </ContentPage.Content>
</ContentPage>

Page1ViewModel:

using System;
using System.ComponentModel;
using System.Windows.Input;

namespace testApp.Views
{
    public class Page1ViewModel:INotifyPropertyChanged
    {
        public Page1ViewModel()
        {
            SaveCommand = new Xamarin.Forms.Command(HandleAction);

        }

        async void HandleAction(object obj)
        {
            await ((testApp.App)App.Current).MainPage.Navigation.PushAsync(
            new Page2()
            {
                BindingContext = new Page2ViewModel(TextPropertyValue)
            }); 

        }
        string entry1;
        public string TextPropertyValue
        {
            get
            {
                return entry1;
            }
            set
            {
                if (value!=entry1)
                {
                    entry1 = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TextPropertyValue)));
                }
            }
        }


        public ICommand SaveCommand
        {
            get;
            set;
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

Page2.xaml:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="testApp.Views.Page2">
    <ContentPage.Content>
    <StackLayout>
        <Label Text="{Binding EntryValue}"/>
            </StackLayout>
    </ContentPage.Content>

Page2.xaml.cs

public partial class Page2 : ContentPage
{
    public Page2()
    {
        InitializeComponent();
    }
}

Page2ViewModel

using System;
namespace testApp.Views
{
    public class Page2ViewModel
    {
        public Page2ViewModel(string entry)
        {
            EntryValue = entry;
        }

        public string EntryValue
        {
            get;
            set;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...