Xamarin Native项目无MVVM框架,如何在App.cs设置启动ViewModel?
在无MVVM框架的Xamarin Native项目中配置启动ViewModel
针对你的需求:使用原生UI控件(iOS用UITableView/UICollectionView,Android用ListView/RecyclerView),采用无框架原生MVVM,实现类似Xamarin.Forms在App.xaml.cs中设置启动页的效果,以下是具体实现步骤:
1. 共享项目中定义全局ViewModel管理逻辑
在共享类库(如.NET Standard项目)中创建App.cs,统一管理启动ViewModel的创建与绑定逻辑:
public class App { // 全局启动ViewModel实例 public static BaseViewModel StartupViewModel { get; private set; } public App() { // 在这里指定你的启动ViewModel StartupViewModel = new MainViewModel(); } // 通用方法:将ViewModel关联到对应平台的View public static void AttachViewModelToView<TView, TViewModel>(TView view, TViewModel viewModel) where TViewModel : BaseViewModel where TView : class { if (view is Android.App.Activity activity) { activity.SetDataContext(viewModel); } else if (view is UIKit.UIViewController vc) { vc.ViewModel = viewModel; } } } // 基础ViewModel类,实现INotifyPropertyChanged以支持数据更新通知 public class BaseViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } // 示例启动ViewModel public class MainViewModel : BaseViewModel { private string _pageTitle = "首页"; public string PageTitle { get => _pageTitle; set { _pageTitle = value; OnPropertyChanged(); } } // 可在此添加业务逻辑、命令等内容 }
2. Xamarin.iOS 平台配置
在iOS项目的AppDelegate.cs中初始化共享项目的App,并将启动ViewModel绑定到根ViewController:
[Register("AppDelegate")] public class AppDelegate : UIApplicationDelegate { public override UIWindow Window { get; set; } public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) { // 初始化共享项目的App实例,创建启动ViewModel var app = new App(); // 创建首页ViewController并绑定ViewModel var mainVC = new MainViewController(); App.AttachViewModelToView(mainVC, App.StartupViewModel); // 设置应用根ViewController Window = new UIWindow(UIScreen.MainScreen.Bounds); Window.RootViewController = mainVC; Window.MakeKeyAndVisible(); return true; } } // iOS首页ViewController示例 public class MainViewController : UIViewController { // 自定义ViewModel属性,用于接收绑定的实例 public BaseViewModel ViewModel { get; set; } public override void ViewDidLoad() { base.ViewDidLoad(); View.BackgroundColor = UIColor.White; if (ViewModel is MainViewModel mainVM) { // 绑定标题到导航栏 NavigationItem.Title = mainVM.PageTitle; // 监听属性变化,实时更新UI mainVM.PropertyChanged += (sender, e) => { if (e.PropertyName == nameof(mainVM.PageTitle)) { NavigationItem.Title = mainVM.PageTitle; } }; } } }
3. Xamarin.Android 平台配置
在Android项目的启动Activity(如MainActivity.cs)中初始化App,并完成ViewModel与Activity的绑定:
[Activity(Label = "@string/app_name", MainLauncher = true)] public class MainActivity : AppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.activity_main); // 初始化共享项目的App实例 var app = new App(); // 绑定ViewModel到当前Activity App.AttachViewModelToView(this, App.StartupViewModel); if (App.StartupViewModel is MainViewModel mainVM) { // 绑定标题到ActionBar SupportActionBar.Title = mainVM.PageTitle; // 监听属性变化,在UI线程更新界面 mainVM.PropertyChanged += (sender, e) => { if (e.PropertyName == nameof(mainVM.PageTitle)) { RunOnUiThread(() => SupportActionBar.Title = mainVM.PageTitle); } }; } } } // 给Android Activity添加DataContext扩展属性,用于存储ViewModel实例 public static class ActivityDataContextExtensions { private static readonly ConditionalWeakTable<Activity, object> _contextStore = new ConditionalWeakTable<Activity, object>(); public static void SetDataContext(this Activity activity, object context) { _contextStore.Remove(activity); _contextStore.Add(activity, context); } public static T GetDataContext<T>(this Activity activity) where T : class { _contextStore.TryGetValue(activity, out object context); return context as T; } }
核心要点
- Xamarin Native为分平台架构,无法像Xamarin.Forms那样直接在
App.cs中设置全局View,因此通过共享项目的App.cs统一管理ViewModel的创建,再在各平台启动入口完成View与ViewModel的绑定。 - 基础ViewModel必须实现
INotifyPropertyChanged接口,才能让ViewModel的属性变化同步到UI。 - 各平台的View需自行处理ViewModel的绑定逻辑,比如监听
PropertyChanged事件更新UI元素。
内容的提问来源于stack exchange,提问作者Samy Gray
相关产品推荐
相关产品推荐

