标签:
Xamarin.Forms 现已升级到 2.0.0.6482 , 正式开启了对 UWP 的支持.
要创建 UWP 项目, 必须是 VS2015, WIN8.1 下也可以, 但是只有 Windows 10 Mobile 的模拟器可用, Windows 10 的模拟器, 必须在 WIN 10 下.
以下简称
Xamarin.Forms 为 XF,
Caliburn.Micro 为 CM
XF的项目模板, 当前没有加入 UWP , 需要手动创建 UWP 项目.
过程如下:
1, 添加一个 UWP 项目
2,添加 Xamarin.Forms 2.0.0.6482 的 Nuget 引用
3, 设置 UWP 项目的部署属性
4, 将 XF PCL 或 Shared 项目引用到 UWP 项目中.
5, 编辑 UWP 项目的 App.xmal.cs , 在 OnLanched 方法中加入 (红色部分):
1 rootFrame.NavigationFailed += OnNavigationFailed; 2 Xamarin.Forms.Forms.Init (e);
6, 修改 MainPage.xaml, 红色部分为变更
1 <forms:WindowsPage 2 x:Class="Notification.UWP.MainPage" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="using:Notification.UWP" 6 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 xmlns:forms="using:Xamarin.Forms.Platform.UWP" 9 mc:Ignorable="d"> 10 11 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 12 13 </Grid> 14 </forms:WindowsPage>
7, 修改 MainPage.xaml.cs, 加入红色部分, Notification.App 是 XF 项目的 App
1 public sealed partial class MainPage { 2 public MainPage() { 3 this.InitializeComponent(); 4 this.LoadApplication(new Notification.App()); 5 } 6 }
OK, 一个 XF 支持的 UWP 就建好了.
CM 3.0 版以经集成了对 XF 项目的支持, 具体可参考:
Xamarin 的 MVVM 之 Caliburn.Micro
CM 3.0 中也加入了对 UWP 的支持, 具体可参考示例:
这里要讲一下, 如何把 UWP / XF / CM 这三个东西加起来.
1, 修改 UWP 项目下的 App.xaml, 红色部分为变更部分
1 <cm:CaliburnApplication 2 x:Class="Notification.UWP.App" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="using:Notification.UWP" 6 xmlns:cm="using:Caliburn.Micro" 7 RequestedTheme="Dark"> 8 9 </cm:CaliburnApplication>
2, 修改 UWP 项目下的 App.xaml.cs , 红色部分为变更
1 public sealed partial class App { 2 private WinRTContainer _container; 3 private IEventAggregator _eventAggregator; 4 5 public App() { 6 InitializeComponent(); 7 } 8 9 protected override void Configure() { 10 _container = new WinRTContainer(); 11 _container.RegisterWinRTServices(); 12 13 14 15 _eventAggregator = _container.GetInstance<IEventAggregator>(); 16 } 17 18 19 protected override IEnumerable<Assembly> SelectAssemblies() { 20 return new[] 21 { 22 GetType().GetTypeInfo().Assembly, 23 typeof (Notification.App).GetTypeInfo().Assembly 24 }; 25 } 26 27 protected override void OnLaunched(LaunchActivatedEventArgs args) { 28 Xamarin.Forms.Forms.Init(args); 29 30 31 this.DisplayRootView<MainPage>(); 32 if (args.PreviousExecutionState == ApplicationExecutionState.Terminated) { 33 //_eventAggregator.PublishOnUIThread(new ResumeStateMessage()); 34 } 35 } 36 37 protected override void OnSuspending(object sender, SuspendingEventArgs e) { 38 //_eventAggregator.PublishOnUIThread(new SuspendStateMessage(e.SuspendingOperation)); 39 } 40 41 protected override object GetInstance(Type service, string key) { 42 return _container.GetInstance(service, key); 43 } 44 45 protected override IEnumerable<object> GetAllInstances(Type service) { 46 return _container.GetAllInstances(service); 47 } 48 49 protected override void BuildUp(object instance) { 50 _container.BuildUp(instance); 51 } 52 }
A, 这个 App 只是一个 partial 的, 不在是从 Application 继承过来的.
B, OnLaunched 方法中 需要 Xamarin.Forms.Init
C, 然后 DisplayRootView MainPage, 这个 MainPage 不是按 CM 的 MVVM 处理的, 只是 XF 页面展示的一个容器.
D, 重写 SelectAssemblies 方法, 返回 UWP 项目的 Assembly 和 XF 项目的 Assembly .
这里返回 XF 项目的 Assembly, 是因为 View / Model 在 XF 项目中定义, 如果不返回它 , 就无法和将 XF 中的 View 和 Model 关联起来.
3, 修改 MainPage.xaml.cs , 红色部分为变更
1 public MainPage() { 2 this.InitializeComponent(); 3 this.LoadApplication(new Notification.App(IoC.Get<WinRTContainer>())); 4 }
Notication.App 的构造函数接收一个 SimpleContainer 的参数, WinRTContainer 是 UWP 下的 SimpleContainer 的实现.
4, 看一下 Notification.App (XF PCL / Shared 项目) 的定义:
public class App : FormsApplication { private SimpleContainer Container = null; public App(SimpleContainer container) { this.Container = container; this.Container .Singleton<HomeViewModel>() .Singleton<MasterViewModel>(); this.DisplayRootView<HomeView>(); } protected override void PrepareViewFirst(NavigationPage navigationPage) { this.Container.Instance<INavigationService>(new NavigationPageAdapter(navigationPage)); } }
SimpleContainer 为 CM 自带的 IoC .
OK, 做完这一步, XF / UWP / CM 这三个东西就揉进一起了.
CM 支技多个 View 使用同一个 Model, 官方档只对这个功能只是用了一小段进行描述, 具体参见:
http://caliburnmicro.com/documentation/composition
搜索 : Multiple Views over the Same ViewModel
也可参考:
简单来说, 就是利用 AttachedProperty : View.Context 来传递一个标识符, 跟据这个标识符加载对应的视图, 如果找不到, 则使用默认的视图.
比如这个 MasterView.xaml 即默认的视图.
如果 View.Context 设为 Windows , 就会去加载 Master/Windows.xaml.
如果 View.Context 为 IOS, 但是不存在 Master/IOS.xaml , 就会默认使用 MasterView.xaml
这是 CM 的一个约定.
XF 项目的目标就是一次编写, 同时生成支持 IOS / Android / WP (SL) / UWP 的 APP.
各个平台的最终表现出什么样的用户界面 , 是由封装在不同 Xamarin.Forms.Platform 中的 Renderer 来负责呈现的.
IOS / Android 有先天的优势, 即使不怎么改, 也不会太丑, 但是 WP , 甚至新的 UWP 项目, 都需要后天的费工费时的一点一点的润色.
在给 WP / UWP 润色的同时, 又不想对 IOS / Android 有影响, CM 的多视图支持是不一个不错的选择.
嗯, 费话了一堆, 看看处理办法吧, 修改 XF 项目的 App.cs
1 public App(SimpleContainer container) { 2 3 this.Container = container; 4 5 this.Container 6 .Singleton<HomeViewModel>() 7 .Singleton<MasterViewModel>(); 8 9 var f = ViewLocator.LocateTypeForModelType; 10 ViewLocator.LocateTypeForModelType = (type, bindable, context) => { 11 return f(type, bindable, context ?? Device.OS) ?? f(type, bindable, context); 12 }; 13 14 this.DisplayRootView<HomeView>(); 15 }
在 App 的构造函数, DisplayRootView 之前, 先保存 ViewLocator.LocateTypeForModelType 到一个变量, 它是一个 Func ,
然后重写这个 Func
如果 context 为 null, 就取 Device.OS 的值.
如果跟据 指定的 conetxt 找不到视图, 就取默认的视图.
OK, 多视图的功能也完成了!
当前 XF 对 UWP 的支持还有 BUG........期待完善...
首先, 添加一个 ViewLocatorPage, 继承自 ContentPage, 使用 CM 进行绑定
1 public class ViewLocatorPage : ContentPage { 2 3 public static readonly BindableProperty VMProperty = BindableProperty.Create<ViewLocatorPage, Screen>(p => p.VM, null, propertyChanged: VMChanged); 4 5 public Screen VM { 6 get { 7 return (Screen)this.GetValue(VMProperty); 8 } 9 set { 10 this.SetValue(VMProperty, value); 11 } 12 } 13 14 15 private static void VMChanged(BindableObject bindable, object oldValue, object newValue) { 16 if (newValue == null) 17 return; 18 19 var vm = (Screen)newValue; 20 //var view = vm.GetView(); 21 var vmView = ViewLocator.LocateForModel(vm, null, null); 22 if (vmView == null) 23 throw new Exception("没有找到视图"); 24 ViewModelBinder.Bind(vm, vmView, null); 25 26 var activator = vm as IActivate; 27 if (activator != null) 28 activator.Activate(); 29 30 var page = (ViewLocatorPage)bindable; 31 if (null != (ContentPage)vmView) { 32 var vp = (ContentPage)vmView; 33 page.Content = vp.Content; 34 if (vp.ToolbarItems != null) 35 foreach (var t in vp.ToolbarItems) 36 page.ToolbarItems.Add(t); 37 } else if (null != (Xamarin.Forms.View)vmView) { 38 page.Content = (Xamarin.Forms.View)vmView; 39 } 40 } 41 42 }
对 MasterDetailPage 绑定:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms" 3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 4 xmlns:cal="clr-namespace:Caliburn.Micro.Xamarin.Forms;assembly=Caliburn.Micro.Platform.Xamarin.Forms" 5 x:Class="Notification.Views.HomeView" 6 xmlns:local="clr-namespace:Notification;assembly=Notification" 7 Title="Notification Test" 8 > 9 10 <MasterDetailPage.Master> 11 <local:ViewLocatorPage Title="TTT" VM="{Binding}" BindingContext="{Binding MasterPage}" /> 12 </MasterDetailPage.Master> 13 14 <MasterDetailPage.Detail Title="AAA"> 15 <ContentPage Title="BBB"></ContentPage> 16 </MasterDetailPage.Detail> 17 </MasterDetailPage>
注意, 一定要使用 BindingContext, MasterPager 为 Model 中的一个属性.
对 TabbedPage 绑定:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" 3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 4 x:Class="Discuz.Views.TabView" 5 xmlns:cal="clr-namespace:Caliburn.Micro.Xamarin.Forms;assembly=Caliburn.Micro.Platform.Xamarin.Forms" 6 xmlns:local="clr-namespace:Discuz;assembly=Discuz" 7 ItemsSource="{Binding Datas}" 8 Title="蓝色理想" 9 BackgroundColor="#1e5263" 10 Padding="0" 11 > 12 13 <TabbedPage.ItemTemplate> 14 <DataTemplate> 15 <local:ViewLocatorPage Title="{Binding DisplayName}" VM="{Binding}" /> 16 </DataTemplate> 17 </TabbedPage.ItemTemplate> 18 19 </TabbedPage>
---------------------------
完, 源码:
https://github.com/gruan01/Xamarin-Example/tree/master/Notification.UWP
标签:
原文地址:http://www.cnblogs.com/xling/p/xamarin-forms-uwp-caliburn-micro.html