走进 Prism for Xamarin.Forms

一、使用环境

OS:Win 10 16273

VS:VS2017- 15.3.4

Xamarin:4.6.3.4,nuget:2.4

Android Emulator:Visual Studio for Android Emulator(相比 Android Emulator不用下载SDK,而且启动快)

二、安装 Prism 模块

工具——扩展和更新——搜索 Prism Template Pack——安装

三、开始搞起

1.先建个项目

2.添加页面

Views文件夹右键——添加——新建项,弹出来的对话框先选中左边的 Prism 节点

确定后,你会发现 App.xaml.cs 文件里注入了新建的页面, ViewModels 文件夹下也多出了 ViewModel ,Views 新添加的文件也是和 ViewModel 绑定好的

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="SD.Xamarin.Views.LoginPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
    Title="Login"
    prism:ViewModelLocator.AutowireViewModel="True">

    <ContentPage.ToolbarItems>
        <ToolbarItem Text="Regist" />
    </ContentPage.ToolbarItems>

    <StackLayout
        Padding="20"
        Spacing="20"
        VerticalOptions="Center">

        <Entry Placeholder="Username" Text="{Binding Username}" />
        <Entry
            IsPassword="true"
            Placeholder="Password"
            Text="{Binding Password}" />

        <Button
            BackgroundColor="#77D065"
            Command="{Binding LoginCommand}"
            Text="Login"
            TextColor="White" />
    </StackLayout>

</ContentPage>
public class LoginPageViewModel : BindableBase
    {
        private readonly INavigationService _navigationService;
        private readonly IEventAggregator _eventAggregator;
        private readonly IPageDialogService _pageDialogService;

        private string _username;

        public string Username
        {
            get { return _username; }
            set
            {
                _username = value;
                RaisePropertyChanged();
            }
        }

        private string _password;

        public string Password
        {
            get { return _password; }
            set
            {
                _password = value;
                RaisePropertyChanged();
            }
        }

        private ICommand _loginCommand;

        public ICommand LoginCommand
        {
            get { return _loginCommand ?? new DelegateCommand(Login); }
            set { _loginCommand = value; }
        }

        public LoginPageViewModel(INavigationService navigationService, IEventAggregator eventAggregator, IPageDialogService pageDialogService)
        {
            _navigationService = navigationService;
            _eventAggregator = eventAggregator;
            _pageDialogService = pageDialogService;
        }

        private async void Login()
        {
            if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password))
            {
                await _navigationService.NavigateAsync(nameof(DataCabinPage));
            }
            else
            {
                await _pageDialogService.DisplayAlertAsync("Error", "Wrong Username or Password", "OK!");
            }
        }
    }

3.添加一个 Master 页面作为主页面

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage
    x:Class="SD.Xamarin.Views.MasterPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:behaviors="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"
    xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
    xmlns:views="clr-namespace:SD.Xamarin.Views;assembly=SD.Xamarin"
    Title="Master"
    prism:ViewModelLocator.AutowireViewModel="True">

    <MasterDetailPage.Master>
        <NavigationPage Title="Required Foo" Icon="hamburger.png">
            <x:Arguments>
                <views:DataCabinPage />
            </x:Arguments>
        </NavigationPage>
    </MasterDetailPage.Master>

</MasterDetailPage>

Master里的子页面

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="SD.Xamarin.Views.DataCabinPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:behaviors="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"
    xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
    Title="DataCabin"
    prism:ViewModelLocator.AutowireViewModel="True">

    <ContentPage.ToolbarItems>
        <ToolbarItem Command="GoBackCommand" Text="Back" />
    </ContentPage.ToolbarItems>

    <ListView
        x:Name="listView"
        CachingStrategy="RecycleElement"
        GroupDisplayBinding="{Binding Key}"
        GroupShortNameBinding="{Binding Key}"
        IsGroupingEnabled="True"
        ItemsSource="{Binding DataCabinsGrouped}"
        SelectedItem="{Binding SelectedDataCabin}">

        <ListView.Behaviors>
            <behaviors:EventToCommandBehavior Command="{Binding ItemTappedCommand}" EventName="ItemTapped" />
        </ListView.Behaviors>
        <ListView.GroupHeaderTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Horizontal">
                        <Image Source="hamburger.png" />
                        <Label
                            FontSize="18"
                            Text="{Binding Key}"
                            TextColor="DeepSkyBlue"
                            VerticalTextAlignment="Center" />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.GroupHeaderTemplate>

        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Label
                        Text="{Binding Name}"
                        TextColor="White"
                        VerticalTextAlignment="Center" />
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>

    </ListView>

</ContentPage>
public class DataCabinPageViewModel : BindableBase
    {
        private readonly INavigationService _navigationService;
        private readonly IEventAggregator _eventAggregator;
        private readonly IPageDialogService _pageDialogService;

        private DataCabinModel _selectedDataCabin;

        public DataCabinModel SelectedDataCabin
        {
            get { return _selectedDataCabin; }
            set
            {
                _selectedDataCabin = value;
                RaisePropertyChanged();
            }
        }

        private ObservableCollection<DataCabinModel> _dataCabins;

        public ObservableCollection<DataCabinModel> DataCabins
        {
            get { return _dataCabins; }
            set
            {
                _dataCabins = value;
                RaisePropertyChanged();
            }
        }

        private ObservableCollection<GroupingModel<string, DataCabinModel>> _dataCabinsGrouped;

        public ObservableCollection<GroupingModel<string, DataCabinModel>> DataCabinsGrouped
        {
            get { return _dataCabinsGrouped; }
            set
            {
                _dataCabinsGrouped = value;
                RaisePropertyChanged();
            }
        }

        private ICommand _itemTappedCommand;

        public ICommand ItemTappedCommand
        {
            get { return _itemTappedCommand ?? new DelegateCommand(ItemTapped); }
            set { _itemTappedCommand = value; }
        }

        private ICommand _goBackCommand;

        public ICommand GoBackCommand
        {
            get { return _goBackCommand ?? new DelegateCommand(GoBack); }
            set { _goBackCommand = value; }
        }

        public DataCabinPageViewModel(INavigationService navigationService, IEventAggregator eventAggregator, IPageDialogService pageDialogService)
        {
            _navigationService = navigationService;
            _eventAggregator = eventAggregator;
            _pageDialogService = pageDialogService;

            DataCabins = new ObservableCollection<DataCabinModel>()
            {
                new DataCabinModel(){Id=1,Name = "T1",GroupName="G1",DisplayType= DataCabinType.Chart},
                new DataCabinModel(){Id=2,Name = "T2",GroupName="G1",DisplayType= DataCabinType.Grid},
                new DataCabinModel(){Id=3,Name = "T3",GroupName="G2",DisplayType= DataCabinType.Guage},
                new DataCabinModel(){Id=4,Name = "T4",GroupName="G2",DisplayType= DataCabinType.Map}
            };

            var grouped = from menuItem in DataCabins
                          orderby menuItem.Id
                          group menuItem by menuItem.GroupName into menuItemGroup
                          select new GroupingModel<string, DataCabinModel>(menuItemGroup.Key, menuItemGroup);

            DataCabinsGrouped = new ObservableCollection<GroupingModel<string, DataCabinModel>>(grouped);
        }

        private async void ItemTapped()
        {
            switch (SelectedDataCabin.DisplayType)
            {
                case DataCabinType.Chart:
                    await _navigationService.NavigateAsync("/Master/Navigation/" + nameof(ChartPage));
                    break;
                case DataCabinType.Grid:
                    await _navigationService.NavigateAsync("/Master/Navigation/" + nameof(GridPage));
                    break;
                case DataCabinType.Guage:
                    await _navigationService.NavigateAsync("/Master/Navigation/" + nameof(GuagePage));
                    break;
                case DataCabinType.Map:
                    await _navigationService.NavigateAsync("/Master/Navigation/" + nameof(MapPage));
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

        }

        private void GoBack()
        {
            _navigationService.NavigateAsync(nameof(DataCabinPage));
        }
    }

App.xaml

public partial class App : PrismApplication
    {
        public App(IPlatformInitializer initializer = null)
            : base(initializer)
        { }

        protected override void OnInitialized()
        {
            InitializeComponent();

            NavigationService.NavigateAsync(nameof(LoginPage));
        }

        protected override void RegisterTypes()
        {
            Container.RegisterTypeForNavigation<NavigationPage>("Navigation");

            Container.RegisterTypeForNavigation<RegistPage>();
            Container.RegisterTypeForNavigation<LoginPage>();
            Container.RegisterTypeForNavigation<MasterPage>("Master");
            Container.RegisterTypeForNavigation<ChartPage>();
            Container.RegisterTypeForNavigation<GridPage>();
            Container.RegisterTypeForNavigation<GuagePage>();
            Container.RegisterTypeForNavigation<MapPage>();
            Container.RegisterTypeForNavigation<DataCabinPage>();
        }
    }

这是最终的 App 文件,注意其中的NavigationPage 和MasterPage 后边都加了参数,用来导航用的,因为想要汉堡包样式

汉堡包的图片是从官方例子复制的,需要放到

Android:

IOS:直接 Resources 文件夹下

导航的写法  await _navigationService.NavigateAsync("/Master/Navigation/" + nameof(ChartPage));  这里就是App.xaml.cs 文件里注册时的那个参数,本来想把前边也写出nameof 的方式,但是发现直接失败了,就只能这样了

其他的代码都很建单,也没写什么逻辑,就不贴了,大概就是这个样子,嗯,下一步就要引入 syncfusion 的控件才行了,这样才好看,也能有很多控件用(主要是实在不知道写什么业务)

动态图

四、模拟器

工具——Visual Studio Emulator for Android 弹出的里边选择一个下载就好了,是基于Hyper-V 的,需要确定你的机器支持

窗口——其他窗口——Xamarin.Forms Previewer 也是可以预览的,但是用了Prism 后,App.xaml.cs 里的构造函数变了,然后就显示不了了~~

五、遇到的问题

1.F5 运行后,执行了 编译——部署,然后就停了,不能像WPF 项目一样实时Debug ,也不知道需要配置什么,这样一旦出错,就得一点点试,很不舒服

2.点击主页后跳转到子页面,再弹出汉堡包跳转第二个,再跳转第三个后 程序就崩溃了,也不知道为什么

3.有时页面的ToolbarItem 不显示,但是放到汉堡包里的那个就显示,不知道怎么搞的,

以上问题有知道的,请多指教啊

六、总结

Xamarin 整合到VS 里后,环境配置相比刚出来时好配置好多,VS Emulator 的加入也省去了下载 Android SDK时的困难,而且还特别大,虽然VS的某些功能还是需要FQ下载。

WP已死,没必要开发,UWP 肯定是回到桌面的 UWP 开发比较好,调试和用法更好用,而且还可以查看虚拟树什么的,好方便的。

CM框架也要出4.0了,到时再试试CM

七、参考例子

Prism:https://github.com/PrismLibrary/Prism-Samples-Forms

Xamarin:https://github.com/xamarin/xamarin-forms-samples

时间: 2024-09-29 11:11:36

走进 Prism for Xamarin.Forms的相关文章

走进 UnitTest for Xamarin.Forms

之前讲了 Xamarin.Forms 的 UITest 走进 UITest for Xamarin.Forms 走进 Xamarin Test Recorder for Xamarin.Forms 但 UnitTest 更是不可缺少的,不管写什么开发都是需要的 以下演示基于 WIN 10 17017 Preview VS 2017 15.4 Visual Studio Emulator for Android ( 5.5" Marshmallow(6.0.0) XXHDPI Phone API

LINKs: Xamarin.Forms + Prism

LINK 1 - How to use Prism with Xamarin.Forms http://brianlagunas.com/first-look-at-the-prism-for-xamarin-forms-preview/ (Note: the Prism.Forms version 6.0.1 doesn't support Xamarin.Forms v2 yet) LINK 2 - Prism GitHub https://github.com/PrismLibrary

Xamarin.Forms+Prism(3)—— 简单提示UI的使用

这次给大家介绍两个比较好用的提示插件,如成功.等待.错误提示. 准备: 1.新建一个Prism Xamarin.Forms项目: 2.右击解决方案,添加NuGet包: 1)Acr.UserDialogs(全部安装): 2)AndHUD(安卓项目安装),BTProgressHUD(iOS项目安装): 设计: 1.我们先介绍第一种Acr.UserDialogs,这个提示插件其实是基于AndHUD和BTProgressHUD,就是说Acr.UserDialogs就是通过实现DependencyServ

Xamarin.Forms开发APP

Xamarin.Forms+Prism(1)-- 开发准备 准备: 1.VS2017(推荐)或VS2015: 2.JDK 1.8以上: 3.Xamarin.Forms 最新版: 4.Prism 扩展,打开VS的扩展和更新,在联机中,搜索Prism,安装第一个扩展Prism Template Pack: 5.Android SDK,这个下载已经非常快了,国内已经支持Android环境下载. 6.都准备好后,请确保创建一个新的Xamarin.Forms程序后,能正常调试运行,不能调试运行的,请百度或

菜鸟的Xamarin.Forms前行之路——原生Toast的简单实现方法

项目中信息提示框,貌似只有个DisplayAlert,信息提示太过于单一,且在有些场合Toast更加实用,以下是一个简单的原生Toast的实现方法 项目地址:https://github.com/weiweu/TestProject/tree/dev/Toast 共享项目 定义一个接口IToast,包括Short和Long两个方法: public interface IToast { void LongAlert(string message); void ShortAlert(string m

张高兴的 Xamarin.Forms 开发笔记:为 Android 与 iOS 引入 UWP 风格的汉堡菜单 ( MasterDetailPage )

所谓 UWP 样式的汉堡菜单,我曾在"张高兴的 UWP 开发笔记:汉堡菜单进阶"里说过,也就是使用 Segoe MDL2 Assets 字体作为左侧 Icon,并且左侧使用填充颜色的矩形用来表示 ListView 的选中.如下图 但怎样通过 Xamarin.Forms ,将这一样式的汉堡菜单带入到 Android 与 iOS 中呢? 一.大纲-细节模式简介 讲代码前首先来说说这种导航模式,官方称"大纲-细节模式"(MasterDetail).左侧的汉堡菜单称为&qu

菜鸟的Xamarin.Forms前行之路——绪言

作者入门时间不是很久,差不多一年,期间自学的东西比较杂乱,到目前为止,编程方面的知识比较薄弱.之所以做这个系列,也只是因为做了两个月的Xamarin.Forms方面的东西,由于资料和自身实力的原因,过程走的比较艰难,但所幸的是也解决了部分的问题,积累了一些经验.期望通过这个系列,和大家分享经验,查漏纠错. 作为一个菜鸟,在解决问题的时候,往往比较直接,就是仅仅为了解决问题,期间可能根本没有考虑性能等方面的问题.所以在这个系列中,问题肯定是作者亲身实践能够解决的,但是在性能资源等方面作者没有做过考

Xamarin.Forms之MessagingCenter

MessagingCenter是Xamarin.Forms中很有用但是很难用的东西,使用起来很方便,但是要注意的地方很多 1.Sender能为空 MessagingCenter.Send<CacheUserInfo>(UserInfo.Instance.CurrentLoginUser, "UpdateMenuIconList"); CurrentLoginUser为空的时候,会直接造成界面卡死(不执行下面的代码,但是也不报错,坑爹的地方)

Xamarin.Forms之Effects的使用

在 Xamarin.Forms 2.1.0-pre1 ,Xamarin.Forms新增了新的Effects API. Effects是一系列方法,为了给View的渲染器添加运行时改变. 然而,我想强调的是, Effects天生被设计为高可复用的. 如果一个Effect能够解决一个难题, 它可能能够在你的整个APP中使用.如果你写了一个Effect来解决你的一个难题, 你能够分享它给其他遇到同样问题的人. 这篇文章尝试展示一种方式,能够帮助我们使分享Effects这件事变得很简单. public