走進 Prism for Xamarin.Forms

1、使用環境html

OS:Win 10 16273git

VS:VS2017- 15.3.4github

Xamarin:4.6.3.4,nuget:2.4app

Android Emulator:Visual Studio for Android Emulator(相比 Android Emulator不用下載SDK,並且啓動快)框架

 

2、安裝 Prism 模塊async

工具——擴展和更新——搜索 Prism Template Pack——安裝ide

3、開始搞起函數

1.先建個項目工具

2.添加頁面ui

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 的控件才行了,這樣纔好看,也能有不少控件用(主要是實在不知道寫什麼業務)

動態圖

 

4、模擬器

工具——Visual Studio Emulator for Android 彈出的裏邊選擇一個下載就行了,是基於Hyper-V 的,須要肯定你的機器支持

窗口——其餘窗口——Xamarin.Forms Previewer 也是能夠預覽的,可是用了Prism 後,App.xaml.cs 裏的構造函數變了,而後就顯示不了了~~

 

 

5、遇到的問題

1.F5 運行後,執行了 編譯——部署,而後就停了,不能像WPF 項目同樣實時Debug ,也不知道須要配置什麼,這樣一旦出錯,就得一點點試,很不舒服

2.點擊主頁後跳轉到子頁面,再彈出漢堡包跳轉第二個,再跳轉第三個後 程序就崩潰了,也不知道爲何 

3.有時頁面的ToolbarItem 不顯示,可是放到漢堡包裏的那個就顯示,不知道怎麼搞的,

以上問題有知道的,請多指教啊

 

6、總結

Xamarin 整合到VS 裏後,環境配置相比剛出來時好配置好多,VS Emulator 的加入也省去了下載 Android SDK時的困難,並且還特別大,雖然VS的某些功能仍是須要FQ下載。

WP已死,不必開發,UWP 確定是回到桌面的 UWP 開發比較好,調試和用法更好用,並且還能夠查看虛擬樹什麼的,好方便的。

CM框架也要出4.0了,到時再試試CM

 

7、參考例子

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

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

相關文章
相關標籤/搜索