如何为Xamarin原生iOS的新页面添加ViewModel&;Android应用程序
上下文:我收到了这个庞大的企业iOS和Android Xamarin本机应用程序,它不使用ViewModels或任何MVVM框架。它确实有一个独立的网络服务层,并且有很多页面,所以从头开始没有任何意义 为什么需要更改:没有MVVM,直接从UI类(片段和视图控制器)调用服务层,并且没有良好的抽象。因此,我将从1视图开始,然后创建TechDebt来转换应用程序的其余部分 我所知道的:如何为Xamarin原生iOS的新页面添加ViewModel&;Android应用程序,xamarin,mvvm,xamarin.android,xamarin.ios,Xamarin,Mvvm,Xamarin.android,Xamarin.ios,上下文:我收到了这个庞大的企业iOS和Android Xamarin本机应用程序,它不使用ViewModels或任何MVVM框架。它确实有一个独立的网络服务层,并且有很多页面,所以从头开始没有任何意义 为什么需要更改:没有MVVM,直接从UI类(片段和视图控制器)调用服务层,并且没有良好的抽象。因此,我将从1视图开始,然后创建TechDebt来转换应用程序的其余部分 我所知道的: 添加MVVM框架需要创建大量更改,尤其是使用导航服务来导航视图,如果在绿色部署应用程序时添加,则最好这样做 如图所示
如何添加ViewController和片段共享的1个viewmodel?我是不是遗漏了什么,是不是比我做的容易多了?不幸的是,你没有遗漏任何东西,你所有的主张都是正确的,你正确地列出了你可以采取的各种方向(以及你不喜欢的方向) Android和Xamarin.iOS并没有考虑数据绑定,而是使用本机接口,只为数据绑定制作了Xamarin.Forms。本机平台使用数据绑定的能力是有限的(如果存在数据绑定,则平台之间不兼容,您必须创建单独的视图模型,并且到目前为止,iOS还没有数据绑定)
因此,Xamarin.iOS和Xamarin.Android中基本上没有数据绑定。完全由您来抽象共享业务模型并将其与用户界面连接。最终能够使用MvvmLight实现这一点。将Nuget包添加到项目中,在核心共享库项目中创建了ViewModelBase:
public abstract class ViewModelBase : GalaSoft.MvvmLight.ViewModelBase
{
private PropertyChangedEventHandler propertyChangedEventHandler;
protected bool IsLoading { get; set; }
public bool RegisteredPropertyEventHandler { get; set; }
public const string ErrorMessagePropertyName = "ErrorMessage";
public string ErrorMessage { get; set; }
public string SuccessMessage { get; set; }
public void RegisterPropertyEventHandler(PropertyChangedEventHandler propertyChangedEventHandler)
{
this.propertyChangedEventHandler = propertyChangedEventHandler;
this.PropertyChanged += propertyChangedEventHandler;
this.RegisteredPropertyEventHandler = true;
}
public void UnegisterPropertyEventHandler()
{
if (this.RegisteredPropertyEventHandler)
{
this.PropertyChanged -= propertyChangedEventHandler;
this.RegisteredPropertyEventHandler = false;
this.propertyChangedEventHandler = null;
}
}
public void TearDown()
{
this.UnegisterPropertyEventHandler();
}
protected void NotifyError (string message)
{
this.ErrorMessage = message;
RaisePropertyChanged (() => ErrorMessage);
}
}
和一个ViewModelLocator
public class ViewModelLocator
{
public const string ABCPageKey = "ABCPage";
public ABCViewModel ABC
{
get
{
return ServiceLocator.Current.GetInstance<ABCViewModel> ();
}
}
public ViewModelLocator ()
{
ServiceLocator.SetLocatorProvider (() => SimpleIoc.Default);
// Register all of the view models
SimpleIoc.Default.Register<ABCViewModel> ();
}
public static void Cleanup ()
{
}
public T GetViewModel<T> ()
{
return ServiceLocator.Current.GetInstance<T> ();
}
}
公共类ViewModelLocator
{
public const string ABCPageKey=“ABCPage”;
公共ABCViewModel ABC
{
得到
{
返回ServiceLocator.Current.GetInstance();
}
}
公共ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(()=>SimpleIoc.Default);
//注册所有视图模型
SimpleIoc.Default.Register();
}
公共静态无效清除()
{
}
公共T GetViewModel()
{
返回ServiceLocator.Current.GetInstance();
}
}
在iOS方面,我已经有了一个BaseUIViewController,所以我在它上面创建了一个BaseViewModelUIViewController
public abstract partial class BaseViewModelUIViewController<T> : BaseUIViewController where T : ViewModelBase
{
public T ViewModel
{
get
{
return App.Locator.GetViewModel<T> ();
}
}
public BaseViewModelUIViewController (IntPtr handle) : base (handle)
{
}
internal virtual void ViewModelPropertyChangedHandler (object sender, PropertyChangedEventArgs e)
{
Console.WriteLine (string.Format ("****** Property Changed for {0} in {1}", e.PropertyName, this.GetType ().Name));
switch (e.PropertyName)
{
default:
break;
}
}
}
public class BaseViewModelFragment<T> : BaseFragment where T : ViewModelBase
{
public T ViewModel
{
get
{
return App.Locator.GetViewModel<T> ();
}
}
public BaseViewModelFragment (string title) : base (title)
{
}
internal virtual void ViewModelPropertyChangedHandler (object sender, PropertyChangedEventArgs e)
{
Console.WriteLine (string.Format ("****** Property Changed for {0} in {1}", e.PropertyName, this.GetType ().Name));
switch (e.PropertyName)
{
default:
break;
}
}
public override void OnDestroyView ()
{
this.ViewModel.TearDown ();
base.OnDestroyView ();
}
}
公共抽象部分类BaseViewModelUIViewController:BaseUIViewController其中T:ViewModelBase
{
公共视图模型
{
得到
{
返回App.Locator.GetViewModel();
}
}
公共BaseViewModelUIViewController(IntPtr句柄):基本(句柄)
{
}
内部虚拟void ViewModelPropertyChangedHandler(对象发送者,PropertyChangedEventArgs e)
{
Console.WriteLine(string.Format(“{1}中{0}的******属性已更改”,e.PropertyName,this.GetType().Name));
开关(如PropertyName)
{
违约:
打破
}
}
}
然后是Android,类似地,我已经有了一个BaseFragment,所以我在它上面创建了一个BaseViewModelFragment
public abstract partial class BaseViewModelUIViewController<T> : BaseUIViewController where T : ViewModelBase
{
public T ViewModel
{
get
{
return App.Locator.GetViewModel<T> ();
}
}
public BaseViewModelUIViewController (IntPtr handle) : base (handle)
{
}
internal virtual void ViewModelPropertyChangedHandler (object sender, PropertyChangedEventArgs e)
{
Console.WriteLine (string.Format ("****** Property Changed for {0} in {1}", e.PropertyName, this.GetType ().Name));
switch (e.PropertyName)
{
default:
break;
}
}
}
public class BaseViewModelFragment<T> : BaseFragment where T : ViewModelBase
{
public T ViewModel
{
get
{
return App.Locator.GetViewModel<T> ();
}
}
public BaseViewModelFragment (string title) : base (title)
{
}
internal virtual void ViewModelPropertyChangedHandler (object sender, PropertyChangedEventArgs e)
{
Console.WriteLine (string.Format ("****** Property Changed for {0} in {1}", e.PropertyName, this.GetType ().Name));
switch (e.PropertyName)
{
default:
break;
}
}
public override void OnDestroyView ()
{
this.ViewModel.TearDown ();
base.OnDestroyView ();
}
}
公共类BaseViewModelFragment:BaseFragment,其中T:ViewModelBase
{
公共视图模型
{
得到
{
返回App.Locator.GetViewModel();
}
}
公共BaseViewModelFragment(字符串标题):基本(标题)
{
}
内部虚拟void ViewModelPropertyChangedHandler(对象发送者,PropertyChangedEventArgs e)
{
Console.WriteLine(string.Format(“{1}中{0}的******属性已更改”,e.PropertyName,this.GetType().Name));
开关(如PropertyName)
{
违约:
打破
}
}
公共覆盖无效OnDestroyView()
{
this.ViewModel.TearDown();
base.OnDestroyView();
}
}
我希望这对其他寻求解决方案的人来说是有意义的
创建ViewModels:很自然,对于创建的每个新ViewModel,我都必须在ViewModelLocator中注册它
使用ViewModels:就用法而言,您只需通过从iOS的“:BaseViewModelUIViewController”或Android的“:BaseViewModelFragment”继承,在UI中使用ViewModel即可以自定义ListView为例。iOS和Android都可以使用listview模型。这需要在本地渲染器中使用表单模型,到目前为止还不错。该应用程序没有太多更新@markwardell,所以我只是将其添加到自述文件中,以便将来的开发人员进行任何更改。如果想要简单,我可能只需要执行一个实现INotifyPropertyChanged的简单BaseViewModel类,并以这种方式执行。