到目前为止,我可以将值传递给另一个 View ,但问题是我不知道如何使用 MVVM 来做到这一点。我尝试了文档和教程仍然没有运气。我怎样才能做到这一点?
我的项目流程:
- 用户将登录,当用户提供正确的信息时,它将返回一个 JSON 数组,其中包含用户的 ContactID。
- 这个 ContactID 现在被传递到另一个 View 。它将用于将服务器同步到本地数据库,反之亦然
我的问题是:
1. 如何使用 MVVM 将数据传递到其他 View ?
2.如何检查数据是否正确传递?
HTTPWebRequest 的输出:
[{"ContactID":"1"}]
我的代码:
LoginPageViewModel.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Input;
using TBSMobileApplication.Data;
using TBSMobileApplication.View;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace TBSMobileApplication.ViewModel
{
public class LoginPageViewModel : INotifyPropertyChanged
{
void OnPropertyChanged(string PropertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
public string username;
public string password;
public string Username
{
get { return username; }
set
{
username = value;
OnPropertyChanged(nameof(Username));
}
}
public string Password
{
get { return password; }
set
{
password = value;
OnPropertyChanged(nameof(Password));
}
}
public class LoggedInUser
{
public int ContactID { get; set; }
}
public ICommand LoginCommand { get; set; }
public LoginPageViewModel()
{
LoginCommand = new Command(OnLogin);
}
public void OnLogin()
{
if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(Password))
{
MessagingCenter.Send(this, "Login Alert", Username);
}
else
{
var current = Connectivity.NetworkAccess;
if (current == NetworkAccess.Internet)
{
var link = "http://192.168.1.25:7777/TBS/test.php?User=" + Username + "&Password=" + Password;
var request = HttpWebRequest.Create(string.Format(@link));
request.ContentType = "application/json";
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
{
Console.Out.WriteLine("Error fetching data. Server returned status code: {0}", response.StatusCode);
}
else
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
if (content.Equals("[]") || string.IsNullOrWhiteSpace(content) || string.IsNullOrEmpty(content))
{
MessagingCenter.Send(this, "Http", Username);
}
else
{
var result = JsonConvert.DeserializeObject<List<LoggedInUser>>(content);
var contactId = result[0].ContactID;
Application.Current.MainPage.Navigation.PushAsync(new DatabaseSyncPage(contactId), true);
}
}
}
}
}
else
{
MessagingCenter.Send(this, "Not Connected", Username);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
DatabaseSyncPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace TBSMobileApplication.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DatabaseSyncPage : ContentPage
{
public DatabaseSyncPage (int contanctId)
{
InitializeComponent ();
}
}
}
最佳答案
如果您是 MVVM 新手,我强烈建议您使用 MVVM 辅助框架,例如 Prism。 , MVVMCross或 MVVMLight (还有更多)。
我自己使用 Prism,我相信所有的框架在功能上都非常相似,在这里更多地归结为偏好。我将向您展示如何在基于 Prism 的应用程序中的 View 之间传递数据。在我们开始之前,值得下载 prism Visual Studio 扩展并使用模板包生成一个 prism 项目。我使用 DryIoc 容器。
想象一下我们有 ViewA(带有 ViewAViewModel)和 ViewB(带有 ViewBViewModel)的场景。在 View A 中,我们有一个条目和一个按钮,当按下按钮时, View A 中条目的文本将传递给 View B,并在其中显示在标签中。
您将首先设置您的 prism 项目,为 View A 和 B 创建一个 XAML 前置 View ,然后创建 2 个类文件并创建相关的 View 模型(我将向您展示如何)。
首先创建以下文件:
在您的 app.cs 中注册 View 和 View 模型:
//You must register these views with prism otherwise your app will crash!
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<ViewA, ViewAViewModel>();
containerRegistry.RegisterForNavigation<ViewB, ViewBViewModel>();
}
现在通过添加以下内容来格式化您的 View 模型:
public class ViewAViewModel : ViewModelBase
{
INavigationService _navigationService;
public ViewAViewModel(INavigationService navigationService) : base(navigationService)
{
Title = "ViewA";
_navigationService = navigationService;
}
}
对 ViewBViewModel 也重复上述步骤(更改相关名称)。
现在在 View 中 xaml 让我们添加一些东西!将以下内容添加到 ViewA.xaml(在
<ContentPage.Content></ContentPage.Content>
内:<StackLayout>
<Entry Placeholder="Type Here..." Text="{Binding ViewAText}"/>
<Button Text="Navigate" Command="{Binding OnNavigateCommand}"/>
</StackLayout>
在 ViewB.xaml 中:
`<Label Text="{Binding TextFromViewA}"/>`
现在我已经为你添加了绑定(bind),让我们来创建属性吧!
在 View 模型 A 中添加:
private string _viewAText;
public string ViewAText
{
get { return _viewAText; }
set { SetProperty(ref _viewAText, value); }
}
public DelegateCommand OnNavigateCommand { get; set; }
private void OnNavigate()
{
//Do Something
}
现在我们有一个可绑定(bind)属性和一个按钮按下命令,将以下内容添加到构造函数中:
public ViewAViewModel(INavigationService navigationService) : base(navigationService)
{
Title = "ViewA";
_navigationService = navigationService;
_viewAText = string.Empty;
OnNavigateCommand = new DelegateCommand(OnNavigate);
}
现在 View A 可以从入口控件绑定(bind)文本,并为命令提供事件处理程序!
让我们跳到 View B 并将其连接起来!
添加属性:
private string _textFromViewA;
public string TextFromViewA
{
get { return _textFromViewA; }
set { SetProperty(ref _textFromViewA, value); }
}
在构造函数中:
public ViewBViewModel(INavigationService navigationService) : base(navigationService)
{
Title = "ViewB";
TextFromViewA = string.Empty;
}
现在我们在 ViewB 中添加的标签已连接到 View 模型。现在让我们将文本从 A 中的条目传递到 B!
返回 View A 将以下内容添加到
OnNavigate
方法:private void OnNavigate()
{
NavigationParameters navParams = new NavigationParameters();
navParams.Add("PassedValue", _viewAText);
_navigationService.NavigateAsync("ViewB", navParams);
}
导航服务非常强大,允许您在 View 之间传递字典 (
NavigationParameters
)。在这段代码中,我们创建了一些 NavigationParameter
,将我们条目中文本的值添加到它们,然后询问navigationService
(它处理来自 Prism 中 View 模型的所有导航)导航到 ViewB,将参数传递给它。在 View B 中,我们可以使用 Prism 提供的一些内置方法来监听这些参数。如果您键入
override
在 ViewBViewModel 你会看到方法:OnNavigatingTo
OnNavigatedTo
OnNavigatedFrom
在这种情况下,我们要使用
OnNavigatingTo
(在 View 之间的转换期间触发)。拉入该方法和以下内容:public override void OnNavigatingTo(NavigationParameters parameters)
{
base.OnNavigatingTo(parameters);
if (parameters.ContainsKey("PassedValue"))
{
_textFromViewA = (string)parameters["PassedValue"];
RaisePropertyChanged("TextFromViewA");
}
}
在这里,我们检查参数是否包含我们添加的值(通过搜索字典键),然后检索该值(将其转换为字符串,因为字典是 )。然后我们将标签绑定(bind)的属性 = 设置为传递的值,然后使用棱镜方法
RaisePropertyChanged()
引发属性更改事件,以便标签的绑定(bind)值更新!下面是结果的gif!
这可能需要考虑很多。我建议您尽快开始使用 MVVM 框架,它们非常易于使用,我认为它们对于制作可测试、解耦的 MVVM xamarin 应用程序至关重要!
有关棱镜如何工作的更多信息,我建议去 read the docs和 watch Brian Lagunas' appearance on the Xamarin Show!
祝你好运!
关于rest - Xamarin 使用 MVVM 将数据传递和检查到其他 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51549737/