走进 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

 

posted @ 2017-09-15 08:43  Blue-G  阅读(1489)  评论(3编辑  收藏  举报