到目前为止,我可以将值传递给另一个视图,但是问题是我不知道如何使用MVVM来执行此操作。我尝试过文档和教程仍然没有运气。我该如何实现?
我的项目流程:
-用户将登录,当用户提供正确的密码时,它将返回一个包含用户的ContactID的JSON数组。
-现在,此ContactID可以传递到另一个视图。它将用于将服务器同步到本地数据库,反之亦然
我的问题是:
1。如何使用MVVM将数据传递到其他视图?
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 ();
}
}
}
答案 0 :(得分:2)
如果您不熟悉MVVM,我强烈建议您使用MVVM帮助程序框架,例如Prism,MVVMCross或MVVMLight(还有更多)。
我本人使用Prism,我相信所有框架在功能上都非常相似,在这里它更倾向于偏好。我将向您展示如何在基于Prism的应用程序中的视图之间传递数据。在我们开始之前,值得下载棱镜Visual Studio扩展并使用模板包来生成一个棱镜项目。我使用DryIoc容器。
想象一下我们有ViewA(带有ViewAViewModel)和ViewB(带有ViewBViewModel)的场景。在视图A中,我们有一个条目和一个按钮,当按下按钮时,ViewA中条目的文本将传递到ViewB,并在标签中显示。
您将首先设置您的棱镜项目,为View A和B创建一个XAML前端视图,然后创建2个类文件并创建相关的View模型(我将向您展示方法)。
首先创建以下文件:
在您的app.cs中注册视图和视图模型:
//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>();
}
现在通过添加以下内容来格式化视图模型:
public class ViewAViewModel : ViewModelBase
{
INavigationService _navigationService;
public ViewAViewModel(INavigationService navigationService) : base(navigationService)
{
Title = "ViewA";
_navigationService = navigationService;
}
}
还对ViewBViewModel重复上述步骤(更改相关名称)。
现在,在视图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}"/>`
现在我已经为您添加了绑定,所以让我们创建属性吧!
在视图模型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
}
现在我们有了一个可绑定的属性和一个用于按下按钮的命令,将以下内容添加到构造函数中:
public ViewAViewModel(INavigationService navigationService) : base(navigationService)
{
Title = "ViewA";
_navigationService = navigationService;
_viewAText = string.Empty;
OnNavigateCommand = new DelegateCommand(OnNavigate);
}
现在视图A可以绑定进入控件中的文本,并具有命令的事件处理程序!
让我们跳进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中添加的标签已连接到视图模型。现在,将文本从A条目传递到B!
返回视图A,将以下内容添加到OnNavigate
方法中:
private void OnNavigate()
{
NavigationParameters navParams = new NavigationParameters();
navParams.Add("PassedValue", _viewAText);
_navigationService.NavigateAsync("ViewB", navParams);
}
导航服务功能强大,可让您在视图之间传递字典(NavigationParameters
)。在此代码中,我们创建了一些NavigationParameter
,并在其中添加了文本值,然后要求navigationService
(处理Prism中从视图模型进行的所有导航)导航至ViewB,并传递参数。
在视图B中,我们可以使用Prism提供的一些内置方法来监听这些参数。如果您在ViewBViewModel中键入override
,则会看到以下方法:
OnNavigatingTo
OnNavigatedTo
OnNavigatedFrom
在这种情况下,我们要使用OnNavigatingTo
(在视图之间的过渡期间触发)。拉入该方法并执行以下操作:
public override void OnNavigatingTo(NavigationParameters parameters)
{
base.OnNavigatingTo(parameters);
if (parameters.ContainsKey("PassedValue"))
{
_textFromViewA = (string)parameters["PassedValue"];
RaisePropertyChanged("TextFromViewA");
}
}
在这里,我们检查参数是否包含我们添加的值(通过搜索字典键),然后检索该值(由于字典为,因此将其广播到字符串中)。然后,将标签绑定到=的属性设置为传递的值,然后使用棱镜方法RaisePropertyChanged()
引发属性更改事件,以便标签的绑定值更新!
下面是结果的gif!
这可能很多。我建议您尽快开始使用MVVM框架,它们确实非常易于使用,并且我认为它们对于制作可测试的,解耦的MVVM xamarin应用程序至关重要!
有关棱镜的工作原理的更多信息,建议您使用read the docs和watch Brian Lagunas' appearance on the Xamarin Show!
祝你好运!
答案 1 :(得分:0)
我已经实施了相同的方法,希望对您有所帮助。
我已经创建了一个loginViewModel
public class LoginVerificationVM : BaseViewModel // INotifyPropertyChanged
{
private INavigation _navigation;
private string usermobileno;
public string UserMobileNo
{ get { return usermobileno; }set { usermobileno = value;
OnPropertyChanged("UserMobileNo"); }
}
public LoginVerificationVM(INavigation navigation, string mobileno)
{
UserMobileNo = mobileno;
_navigation = navigation;
}
public Command Login
{
get
{
return new Command(async () =>
{
bool status = await WebApi.CheckNetWorkStatus();
if (status == false)
{
MessageClass.messagesWindow("Check Ur Connectivity");
this.Isvisible = false;
return;
}
Isvisible = true;
UserAuth ud = new UserAuth();
ud.username = UserMobileNo; // UserMobileNo;
ud.password = Password; // Password
ud.grant_type = "password"; //GrantType
Isvisible = true;
// IsBusy = false;
await Task.Delay(100);
var json = Task.Run(() => WebApi.GetUserAuth(ud)).Result;
// IsBusy = false;
if (json.ErrorMessage == "true")
{
Application.Current.MainPage = new MasterPages.MasterPage(json.access_token); //or use _navigation.PushAsync(new ForgotPasswordOTP(UserMobileNo));
}
else
{
MessageClass.messagesWindow(json.ErrorMessage);
}
Isvisible = false;
});
}
}
}
Xaml代码
<Entry x:Name="PasswordEntry" Grid.Row="2" IsPassword="True" Placeholder="******" HorizontalTextAlignment="Center" FontAttributes="Bold" TextColor="Black" WidthRequest="150" HeightRequest="35" FontSize="13" Text="{Binding Password, Mode=TwoWay}" >
<Button x:Name="Login" Grid.Row="3" HorizontalOptions="Center" BorderRadius="8" Text="Login" WidthRequest="100" BackgroundColor="#f7941d" TextColor="White" Command="{Binding Login}" IsEnabled="{Binding Active,Mode=TwoWay}">
这是获取导航页面视图模型数据的实现方式
public ForgotPasswordOTP(string Ph)
{
InitializeComponent();
BindingContext = new ForgotPasswordOTPViewModel(this.Navigation,Ph);
}
最后要做的就是将视图与viewmodel绑定
** BindingContext = new LoginVerificationVM(this.Navigation);**
最后一个问题的答案是您需要在C#中反序列化json 可以通过以下方式完成
var userData = JsonConvert.DeserializeObject<YourObject>(result);