首页 > 解决方案 > Xamarin.Forms 使用 MVVM 在屏幕之间传输数据

问题描述

我有两个屏幕。

第一个有两个Entries和保存按钮,第二个有两个Labels

两者都有对应的 bind ViewModels

例如第一个XAML

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

第一个视图模型:

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
    }

}

有什么简单的方法可以从第一个屏幕条目中获取字符串并使用 ViewModels 将它们传递给第二个屏幕标签?

标签: c#xamlxamarinmvvmxamarin.forms

解决方案


我已经为您实现了非常简化的示例。当然,执行以下操作并不是最好的实现:

((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/

消息服务是我可以推荐的关于导航的最糟糕的事情,因为它很难理解代码并且调试是一团糟。通过解耦代码,您可以使依赖的事物独立,并且新人无法了解代码的工作原理。当您将事件从内部视图模型传递到根页面视图模型或从视图模型传递到视图或页面时,消息传递很好,但它不适合导航任务。

我的简单示例可以在下面找到: 应用程序代码:

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;
        }
    }
}

推荐阅读