XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書

2016/12/31

Xamarin.Forms 無法進行 Android 實體手機除錯

當您在進行 Xamarin.Forms 專案開發的時候,您的 Android 專案可以正常在模擬器上執行與除錯,可是,當要在實體 Android 手機上進行除錯的時候,卻得到底下錯誤訊息:
Couldn't connect to logcat, GetProcessId returned: 0 
這個時候,您可以使用滑鼠雙擊 Android 專案下的 Properties 項目,接著,在 Properties 視窗中,點選 Android Option > Packaging ,請取消 Use Fast Depolyment (debug mode only) 這個選項。
接著,請清除整個方案,重新建置 Android 專案,接著進行除錯,相信您的應用程式,已經可以在實體手機上進行除錯了。

2016/12/23

如何使用 Zoom 的功能

若您是第一次使用 Zoom,並且已經進入到全螢幕模式,這個時候,請將游標移到中間最上方的區域,此時,會出現 Zoom 的彈出功能表,您可以點選 [退出全螢幕] 功能,就會進入到 Zoom 的視窗模式。



當進入到視窗模式,左下方有一個麥克風圖示,儘可能切換到下圖的麥克風模式,也就是有條紅色斜線的模式,在這個模式下,你的麥克風是在靜音模式;這樣做的目的是,儘可能不會因為你的麥克風有啟動,造成有不同的聲音在會議中,使得會議品質降低。

不過,當您需要講話的時候,可以點選左下角的麥克風圖示,讓麥克風可以啟用,這樣,您就可以透過麥克風,與會議中的所有人溝通。



若需要使用聊天室功能,請點選最下方的 (1) [聊天] 按鈕,此時,右方會出現一塊 (2) 區域,您可以在右下方的區域打入您要讓其他人看到的文字,大家打的文字,就會在 (3) 區域顯示出來。

若在會議中或者任何時候,可以點選 (4) [舉手] 功能,此時,會議主持人就會看到你的舉手動作,這樣,會議主持人就會可以與你產生互動,或者,讓你透過啟用麥克風,讓您可以在會議中講話。

2016/12/11

設計可以動態繪製2D圖形的 Xamarin.Forms App

SkiaSharp是可以在 Xamarin.Forms 的核心PCL專案內,產生 2D 圖形的一個控制項,有了這個擴充控制項,您可以使用 Xamarin.Forms 開發出一個資料蒐集應用程式,並且可以將蒐集到的數據,以圖形的方式顯示在手機螢幕上。
底下為這個範例程式的執行結果。
在這個範例中將會展示如何使用 SkiaSharp 這個套件,在核心PCL專案內,進行2D圖形繪製,要使用這個功能,您需要在方案內的所有專案,安裝這個 SkiaSharp.Views.Forms NuGet 套件。
這個範例專案的原始碼位於
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage 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"
             xmlns:views="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFSkiaSharp.Views.MainPage"
             Title="MainPage">
    <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
        <views:SKCanvasView  
            HorizontalOptions="Fill" VerticalOptions="Start"
            HeightRequest="400"
            x:Name="Canvas" PaintSurface="OnPaintSample"
            Margin="0,0,0,0" />
        <Label Text="{Binding Title}" />
        <StackLayout
            Orientation="Horizontal">
            <Button x:Name="myBtn收集資料" Text="收集資料" />
            <Button x:Name="myBtn畫點" Text="畫點" />
            <Button x:Name="myBtn畫線" Text="畫線" />
            <Button x:Name="myBtn清除" Text="清除" />
        </StackLayout>
    </StackLayout>
</ContentPage>
using SkiaSharp;
using Xamarin.Forms;
using SkiaSharp.Views.Forms;
using System;

namespace XFSkiaSharp.Views
{
    public enum 重繪狀態
    {
        第一次初始化,
        清除,
        繪製點,
        繪製線,
        收集資料
    }
    public partial class MainPage : ContentPage
    {
        public 重繪狀態 _重繪狀態 { get; set; } = 重繪狀態.第一次初始化;
        public MainPage()
        {
            InitializeComponent();

            myBtn清除.Clicked += (s, e) =>
              {
                  _重繪狀態 = 重繪狀態.清除;
                  Canvas.InvalidateSurface();
              };

            myBtn畫線.Clicked += (s, e) =>
              {
                  _重繪狀態 = 重繪狀態.繪製線;
                  Canvas.InvalidateSurface();
              };

            myBtn畫點.Clicked += (s, e) =>
            {
                _重繪狀態 = 重繪狀態.繪製點;
                Canvas.InvalidateSurface();
            };
            myBtn收集資料.Clicked += (s, e) =>
            {
                _重繪狀態 = 重繪狀態.收集資料;
                Canvas.InvalidateSurface();
            };
        }

        int surfaceWidth;
        int surfaceHeight;
        SKCanvas myCanvas;
        private void OnPaintSample(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e)
        {
            surfaceWidth = e.Info.Width;
            surfaceHeight = e.Info.Height;
            myCanvas = e.Surface.Canvas;
            float side = Math.Min(surfaceHeight, surfaceWidth) * 0.5f;

            switch (_重繪狀態)
            {
                case 重繪狀態.第一次初始化:
                    myCanvas.Clear(Color.Gray.ToSKColor());  //paint it black
                    break;
                case 重繪狀態.清除:
                    myCanvas.Clear(Color.Black.ToSKColor());  //paint it black
                    myCanvas.Clear(Color.Red.ToSKColor());  //paint it black
                    myCanvas.Clear(Color.Blue.ToSKColor());  //paint it black
                    myCanvas.Clear(Color.Gray.ToSKColor());  //paint it black
                    break;
                case 重繪狀態.繪製點:
                    var foo = 1;
                    using (SKPaint paint = new SKPaint())
                    {
                        paint.Color = Color.FromHex("00FF00").ToSKColor();
                        paint.StrokeWidth = 5;
                        Random rm = new Random();
                        for (int i = 0; i < 3000; i++)
                        {
                            //myCanvas.DrawPoint(rm.Next(300), rm.Next(300), SKColor.Parse("#00eFF00"));
                            myCanvas.DrawPoint(rm.Next(surfaceWidth), rm.Next(surfaceHeight), paint);
                        }
                    }
                    break;
                case 重繪狀態.收集資料:
                    using (SKPaint paint = new SKPaint())
                    {
                        paint.Color = Color.FromHex("FF0000").ToSKColor();
                        paint.StrokeWidth = 3;
                        Random rm = new Random();
                        for (int i = 0; i < surfaceWidth; i++)
                        {
                            var fooPM = rm.Next(10);
                            if (fooPM >= 5)
                            {
                                fooPM = -1;
                            }
                            else
                            {
                                fooPM = 1;
                            }

                            var fooY = surfaceHeight - (32 + i / 3 + (rm.Next(10) * fooPM));
                            var fooX = i;
                            myCanvas.DrawPoint(fooX, fooY, paint);
                        }
                    }
                    break;
                case 重繪狀態.繪製線:
                    using (SKPaint paint = new SKPaint())
                    {
                        paint.Color = Color.Pink.ToSKColor();
                        paint.StrokeWidth = 7;
                        Random rm = new Random();
                        var fooPreX = 0;
                        var fooPreY = surfaceHeight - 100;
                        for (int i = 0; i < surfaceWidth / 10; i++)
                        {
                            var fooPM = rm.Next(13);
                            if (fooPM >= 5)
                            {
                                fooPM = -1;
                            }
                            else
                            {
                                fooPM = 1;
                            }

                            var fooY = surfaceHeight - (100 + i + (rm.Next(50) * fooPM));
                            var fooX = i * 10;
                            myCanvas.DrawLine(fooPreX, fooPreY, fooX, fooY, paint);
                            fooPreX = fooX;
                            fooPreY = fooY;
                        }
                    }
                    break;
                default:
                    break;
            }
            return;
            using (SKPaint paint = new SKPaint())
            {
                myCanvas.Clear(Color.Gray.ToSKColor());  //paint it black
                SKRect r1 = new SKRect(10f, 20f, side, side);
                paint.Color = Color.Blue.ToSKColor();
                myCanvas.DrawRect(r1, paint);

                paint.Color = Color.Red.ToSKColor();
                myCanvas.DrawOval(r1, paint);

                paint.Color = Color.FromHex("00FF00").ToSKColor();
                paint.StrokeWidth = 5;

                Random rm = new Random();
                for (int i = 0; i < 3000; i++)
                {
                    myCanvas.DrawPoint(rm.Next(300), rm.Next(300), paint);
                    //myCanvas.DrawPoint(rm.Next(300), rm.Next(300), SKColor.Parse("#00FF00"));
                }

                paint.Color = Color.Green.ToSKColor();
                paint.TextSize = 64.0f;
                paint.IsAntialias = true;
                paint.Color = new SKColor(0x9C, 0xAF, 0xB7);
                paint.IsStroke = true;
                paint.StrokeWidth = 3;
                paint.TextAlign = SKTextAlign.Center;

                myCanvas.DrawText("這是Xamarin.Forms", 200f, 200f, paint);
                myCanvas.DrawText("這是Xamarin.Forms", surfaceWidth / 2f, surfaceHeight / 2f, paint);
            }
        }
    }
}

2016/12/10

使用 Visual Studio 2015 增加 Prism 專案樣版

安裝 Prism Template Pack

  1. 首先,開啟 Visual Studio 2015
  2. 點選功能表 工具 > 擴充功能與更新 選項
  3. 在 擴充功能與更新 對話窗內,點選 線上 > Visual Studio 組件庫
  4. 在右上方文字輸入盒內,輸入 Prism Template Pack ,並且按下 Enter 按鍵
  5. 點選搜尋出來的 Prism Template Pack 項目,點選 下載 按鈕,安裝 Prism Template Pack 組件到您的Visual Studio 2015 內;安裝完成後,您需要點選 立即重新啟動 按鈕,讓您的 Visual Studio 2915 重新啟動之後,這次的安裝才會生效。
    PrismTemplatePack
    PrismTemplatePack下載與安裝

2016/12/05

安裝 Visual Studio 2017 並且測試 Xamarin.Forms 過程記錄

之前,使用的是 Azure 上的 VM,進行 Visual Studio 2017,不過,因為無法在 VM 內啟動 Android Emulator;經過 保哥 提示,現在 Windows 10 已經可以支援巢狀 VM,所以,就安裝好一套 Windows 10 VM,並且已經啟動了 Hyper-V 服務,接下來的文章,將會說明如何進行 Visual Studio 2017 的安裝與設定。
我這裡是從 MSDN 訂閱內,取得了 Visual Studio 2017 的安裝檔案 mu_visual_studio_enterprise_2017_rc_x86_x64_9574850.exe ,不到 1MB 的大小,請直接點選並執行這個檔案。
此時,會看到如下圖,請點選 繼續 按鈕,同意授權條款。
enter image description here
在 Visual Studio 2017 中,安裝模式已經有做了修改,在這裡,我們先要選擇 分類為 Windows通用 Windows 平台開發 項目,在選擇完成之後,在右邊面板,記得要參考下圖,一併勾選適當的項目,例如,不同版本的 SDK與行動裝置模擬器。
enter image description here
接著,在分類為 行動與遊戲 的 分類中,選擇 Mobile Development with .NET (Preview) 這個項目,接著,把右方面板的項目全部選取。
enter image description here
請切換到 個別元件,找到 模擬器 分類,勾選 Android 版 Visual Studio 模擬器
enter image description here
最後,按下 安裝 按鈕,開始進行安裝,會出現下圖畫面。
enter image description here
Visual Studio 2017 會開始邊下載,邊進行安裝作業。等到安裝完成之後,就可以點選 啟動 按鈕,啟動 Visual Studio 2017。
enter image description here
在 Visual Studio 2017 第一次啟動的時候,我這裡點選 登入 按鈕,進行登入作業,當然,你也可以點選 不是現在,以後再說 ,讓 Visual Studio 2017 進行首次初始化工作。
enter image description here
為了要能夠在 Visual Studio 2017 RC 進行 Xamarin.Forms 專案的建立工作,我在這裡安裝了 Prism Template Pack 這個擴充功能,請點選功能表的 工具 > 擴充功能與更新 > 線上 接著在右上方的搜尋文字輸入盒內,輸入 Prism Template Pack ,並且安裝這個擴充功能。 請在 Prism Template Pack 項目上,點選 下載 按鈕,當下載完成之後,接者點選 關閉 按鈕,此時,可以先把 Visual Studio 2017 先關閉起來,以便可以順利安裝這個擴充套件。
當出現了 VSIX 安裝程式 對話窗的時候,請點選 安裝 按鈕。
enter image description here
在安裝完成之後,你可以重新啟動 Visual Studio 2017RC。
請點選功能表 工具 > Visual Studio Emulator for Android ,下載與啟動 Android 模擬器。
enter image description here
請下載 5.2” Marshmallow (6.0.0) XXHDPI Phone API Level 23 (Marshmallow 6.0.0) 這個模擬器,並且啟動它。
當您下載完成之後,會出現這段訊息:
You were previously added to the Hyper-V Administrators security group, but the permissions have not taken effect. Please sign out of your computer for the permission to take effect.
請您關閉 Visual Studio Emulator for Android & Visual Studio 2017RC,並且登出作業系統,接著重新登入 Windows 作業系統,打開 Visual Studio 2017 & 啟動剛剛下載完成的模擬器。
在 Visual Studio 2017RC中,點選功能表 檔案 > 新增 > 專案 > 範本 > Visual C# > Prism > Prism Unity App (Xamarin.Forms) 後,請點選右下方 確定 按鈕。
當出現了 PRISM PROJECT WIZARD 對話窗,請勾選 ANDROID & iOS & UWP 這三個類型專案,接著點選 CREATE PROJECT ,完成建立一個以 Prims 為基礎的 Xamarin.Forms 專案。
enter image description here
在專案完成之後,首先會看到底下訊息,請點選這個錯誤訊息,以便進行下載。
嚴重性 程式碼 說明  專案  檔案  行   Suppression State
錯誤      Project 'PrismUnityApp2.Droid' requires the following components installed on your machine: 
Xamarin.Android.Support.Animated.Vector.Drawable
JavaLibraryReference: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/animated-vector-drawable/23.3.0/animated-vector-drawable-23.3.0.aar-23.3.0.0
AndroidResources: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/animated-vector-drawable/23.3.0/animated-vector-drawable-23.3.0.aar-23.3.0.0
Xamarin.Android.Support.Vector.Drawable
JavaLibraryReference: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/support-vector-drawable/23.3.0/support-vector-drawable-23.3.0.aar-23.3.0.0
AndroidResources: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/support-vector-drawable/23.3.0/support-vector-drawable-23.3.0.aar-23.3.0.0
Xamarin.Android.Support.v4
JavaLibraryReference: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/support-v4/23.3.0/support-v4-23.3.0.aar-23.3.0.0
JavaLibraryReference: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/support-v4/23.3.0/support-v4-23.3.0.aar-23.3.0.0
AndroidResources: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/support-v4/23.3.0/support-v4-23.3.0.aar-23.3.0.0
Xamarin.Android.Support.Design
JavaLibraryReference: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/design/23.3.0/design-23.3.0.aar-23.3.0.0
AndroidResources: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/design/23.3.0/design-23.3.0.aar-23.3.0.0
Xamarin.Android.Support.v7.AppCompat
JavaLibraryReference: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/appcompat-v7/23.3.0/appcompat-v7-23.3.0.aar-23.3.0.0
AndroidResources: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/appcompat-v7/23.3.0/appcompat-v7-23.3.0.aar-23.3.0.0
Xamarin.Android.Support.v7.CardView
JavaLibraryReference: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/cardview-v7/23.3.0/cardview-v7-23.3.0.aar-23.3.0.0
AndroidResources: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/cardview-v7/23.3.0/cardview-v7-23.3.0.aar-23.3.0.0
Xamarin.Android.Support.v7.MediaRouter
JavaLibraryReference: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/mediarouter-v7/23.3.0/mediarouter-v7-23.3.0.aar-23.3.0.0
JavaLibraryReference: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/mediarouter-v7/23.3.0/mediarouter-v7-23.3.0.aar-23.3.0.0
AndroidResources: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/mediarouter-v7/23.3.0/mediarouter-v7-23.3.0.aar-23.3.0.0
Xamarin.Android.Support.v7.RecyclerView
JavaLibraryReference: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/recyclerview-v7/23.3.0/recyclerview-v7-23.3.0.aar-23.3.0.0
AndroidResources: https://dl-ssl.google.com/android/repository/android_m2repository_r29.zip-m2repository/com/android/support/recyclerview-v7/23.3.0/recyclerview-v7-23.3.0.aar-23.3.0.0


Please double-click here to install it.         0   
請分別執行各個專案,確認可以正常編譯、執行。

2016/12/04

在 Xamarin.Forms 使用旋轉木馬 CarouselView 控制項,可以左右翻轉

當您需要讓使用者可以在螢幕上,透過手勢左右滑動,看到不同的資料內容,如下圖所呈現的效果。

這個時候,您可以選擇使用旋轉木馬 CarouselView 這個控制項,要使用這個控制項,您需在方案中,加入這個 NuGet 套件到所有的專案內,此時,請在 NuGet 套件安裝視窗中,輸入 Xamarin.Forms.CarouselView ,但是,你將無法看到這個套件,請將旁邊的 包含搶鮮版 檢查盒打勾,就會看到這個套件了。
參考專案原始碼
https://github.com/vulcanlee/xamarin-forms-develop-notes-example/tree/master/XFCarouselView
參考文章
https://blog.xamarin.com/flip-throug
h-items-with-xamarin-forms-carouselview/


正在嘗試針對專案 'XFCarouselView' 及目標 '.NETPortable,Version=v4.5,Profile=Profile259' 收集封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的相依性資訊
收集相依性資訊花費了 5.12 sec
嘗試解析具有 DependencyBehavior 'Lowest' 之封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的相依性
解析相依性資訊花費了 0 ms
正在解析安裝封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的動作
已解析安裝封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的動作


正在嘗試針對專案 'XFCarouselView.Droid' 及目標 'MonoAndroid,Version=v7.0' 收集封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的相依性資訊
收集相依性資訊花費了 24.33 sec
嘗試解析具有 DependencyBehavior 'Lowest' 之封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的相依性
解析相依性資訊花費了 0 ms
正在解析安裝封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的動作
已解析安裝封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的動作


正在嘗試針對專案 'XFCarouselView.iOS' 及目標 'Xamarin.iOS,Version=v1.0' 收集封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的相依性資訊
收集相依性資訊花費了 16.53 sec
嘗試解析具有 DependencyBehavior 'Lowest' 之封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的相依性
解析相依性資訊花費了 0 ms
正在解析安裝封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的動作
已解析安裝封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 的動作
正在還原 'XFCarouselView.UWP' 封裝。
正在還原 C:\Vulcan\GitBook\Temp\XFCarouselView\XFCarouselView\XFCarouselView.UWP\project.json 的封裝...
  GET https://api.nuget.org/v3-flatcontainer/xamarin.forms.carouselview/index.json
  OK https://api.nuget.org/v3-flatcontainer/xamarin.forms.carouselview/index.json 973ms
  GET https://api.nuget.org/v3-flatcontainer/xamarin.forms.carouselview/2.3.0-pre2/xamarin.forms.carouselview.2.3.0-pre2.nupkg
  OK https://api.nuget.org/v3-flatcontainer/xamarin.forms.carouselview/2.3.0-pre2/xamarin.forms.carouselview.2.3.0-pre2.nupkg 921ms
正在安裝 Xamarin.Forms.CarouselView 2.3.0-pre2。
已成功完成 'XFCarouselView.UWP' 的封裝還原。
正在從 'nuget.org' 擷取封裝 'Xamarin.Forms.CarouselView 2.3.0-pre2'。
正在將封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 加入資料夾 'C:\Vulcan\GitBook\Temp\XFCarouselView\packages'
已將封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 加入資料夾 'C:\Vulcan\GitBook\Temp\XFCarouselView\packages'
已將封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 加入 'packages.config'
已成功將 'Xamarin.Forms.CarouselView 2.3.0-pre2' 安裝到 XFCarouselView
執行 NuGet 動作花費了 1.23 sec
在 'C:\Vulcan\GitBook\Temp\XFCarouselView\packages' 中找到封裝 'Xamarin.Forms.CarouselView 2.3.0-pre2'。
封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 已經存在於資料夾 'C:\Vulcan\GitBook\Temp\XFCarouselView\packages'
已將封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 加入 'packages.config'
已成功將 'Xamarin.Forms.CarouselView 2.3.0-pre2' 安裝到 XFCarouselView.Droid
執行 NuGet 動作花費了 4.22 sec
在 'C:\Vulcan\GitBook\Temp\XFCarouselView\packages' 中找到封裝 'Xamarin.Forms.CarouselView 2.3.0-pre2'。
封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 已經存在於資料夾 'C:\Vulcan\GitBook\Temp\XFCarouselView\packages'
已將封裝 'Xamarin.Forms.CarouselView.2.3.0-pre2' 加入 'packages.config'
已成功將 'Xamarin.Forms.CarouselView 2.3.0-pre2' 安裝到 XFCarouselView.iOS
執行 NuGet 動作花費了 840.61 ms
Writing lock file to disk. Path: C:\Vulcan\GitBook\Temp\XFCarouselView\XFCarouselView\XFCarouselView.UWP\project.lock.json
正在產生 MSBuild 檔案 XFCarouselView.UWP.nuget.targets。
已成功將 'Xamarin.Forms.CarouselView 2.3.0-pre2' 安裝到 XFCarouselView.UWP
========== 已完成 ==========
經過時間: 00:00:57.0114984
要了要能夠在 CarouselView 內可以使用 ViewModel 的 ICommand 來綁定點選事件,請也在所有的專案內,安裝這個套件 Behaviors.Forms
在這裡,將建立一個專案,並且將上述兩個套件,安裝到所有的專案內,接著,在 View 中,定義底下的 XAML。
在這裡加入了兩個命名空間 cv 用來指向 旋轉木馬控制項之用,behaviors 用來指向擴充的行為定義之用。
在 CarsouselView 控制項內,因為本身沒有提供相關 ICommand 可綁定屬性,因此,透過了行為來定義了,當 CarsoulerView 的資料有更換的時候,也就是 ItemSelected 事件有被驅動的時候,就會執行 CarouselView點選 這個 Command,這是透過了底下的 XAML宣告,
            <cv:CarouselView.Behaviors>
                <behaviors:EventHandlerBehavior EventName="ItemSelected">
                    <behaviors:InvokeCommandAction Command="{Binding CarouselView點選Command}"
                                                  />
                    <!--<behaviors:InvokeCommandAction Command="{Binding CarouselView點選Command}"
                                                   Converter="{StaticResource SelectedItemChangedEventArgsConverter}"/>-->
                </behaviors:EventHandlerBehavior>
            </cv:CarouselView.Behaviors>
底下是完整的 XAML 宣告
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage 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"
             xmlns:cv="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView"
             xmlns:behaviors="clr-namespace:Behaviors;assembly=Behaviors"
             xmlns:local="clr-namespace:XFCarouselView"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFCarouselView.Views.MainPage"
             Title="MainPage"
             x:Name="ThisPage"
             >

    <ContentPage.Resources>
        <ResourceDictionary>
            <local:SelectedItemChangedEventArgsConverter x:Key="SelectedItemChangedEventArgsConverter" />
        </ResourceDictionary>
    </ContentPage.Resources> 


    <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
        <Label Text="{Binding Title}" />
        <cv:CarouselView x:Name="CarouselZoos"
            ItemsSource="{Binding Zoos}" 
            HorizontalOptions="Fill"
            HeightRequest="180" WidthRequest="300">
            <cv:CarouselView.Behaviors>
                <behaviors:EventHandlerBehavior EventName="ItemSelected">
                    <behaviors:InvokeCommandAction Command="{Binding CarouselView點選Command}"
                                                  />
                    <!--<behaviors:InvokeCommandAction Command="{Binding CarouselView點選Command}"
                                                   Converter="{StaticResource SelectedItemChangedEventArgsConverter}"/>-->
                </behaviors:EventHandlerBehavior>
            </cv:CarouselView.Behaviors>
            <cv:CarouselView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <Image Grid.RowSpan="2" Aspect="AspectFill" Source="{Binding ImageUrl}"/>
                        <StackLayout Grid.Row="1" BackgroundColor="#80000000" Padding="12">
                            <Label TextColor="White" Text="{Binding Name}" FontSize="16" HorizontalOptions="Center" VerticalOptions="CenterAndExpand"/>
                        </StackLayout>
                    </Grid>
                </DataTemplate>
            </cv:CarouselView.ItemTemplate>
        </cv:CarouselView>
        <Label Text="{Binding Title}" />
    </StackLayout>
</ContentPage>
ViewModel 的程式碼如下
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using Prism.Services;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Xamarin.Forms;
using XFCarouselView.Models;

namespace XFCarouselView.ViewModels
{
    public class MainPageViewModel : BindableBase, INavigationAware
    {
        private string _title;
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }
        #region Zoos
        private ObservableCollection<Zoo> _Zoos;
        /// <summary>
        /// Zoos
        /// </summary>
        public ObservableCollection<Zoo> Zoos
        {
            get { return _Zoos; }
            set { SetProperty(ref _Zoos, value); }
        }
        #endregion

        private readonly INavigationService _navigationService;

        public readonly IPageDialogService _dialogService;
        public MainPageViewModel(INavigationService navigationService, IPageDialogService dialogService)
        {

            _dialogService = dialogService;
            _navigationService = navigationService;
            Zoos = new ObservableCollection<Zoo>
            {
                new Zoo
                {
                ImageUrl = "http://content.screencast.com/users/JamesMontemagno/folders/Jing/media/23c1dd13-333a-459e-9e23-c3784e7cb434/2016-06-02_1049.png",
                Name = "Woodland Park Zoo"
                },
                new Zoo
                {
                ImageUrl =    "http://content.screencast.com/users/JamesMontemagno/folders/Jing/media/6b60d27e-c1ec-4fe6-bebe-7386d545bb62/2016-06-02_1051.png",
                Name = "Cleveland Zoo"
                },
                new Zoo
                {
                ImageUrl = "http://content.screencast.com/users/JamesMontemagno/folders/Jing/media/e8179889-8189-4acb-bac5-812611199a03/2016-06-02_1053.png",
                Name = "Phoenix Zoo"
                }
            };

            CarouselView點選Command = new DelegateCommand<SelectedItemChangedEventArgs>( x =>
            {
                var foo = x.SelectedItem as Zoo;
                //await _dialogService.DisplayAlertAsync("Infor", $"Selected {foo.Name}", "OK");

                Title = $"Selected {foo.Name}";
            });
        }

        public DelegateCommand<SelectedItemChangedEventArgs> CarouselView點選Command { get; set; }

        public DelegateCommand CarouselViewTest點選Command { get; set; }


        public void OnNavigatedFrom(NavigationParameters parameters)
        {
        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {
            if (parameters.ContainsKey("title"))
                Title = (string)parameters["title"] + " and Prism";
        }
    }
}

2016/12/03

如何在 Xamarin.Forms 製作出一個浮動功能表應用

當您有需要作出一個類似 Gmail 的浮動且可彈出與收起的功能表應用效果,當然,可以優先選擇購買付費的控制項;若您想要省點錢,並且做出這樣的效果,可以參考這篇文章,作出如下圖動畫效果。

這裡只是簡單應用了 Data Binding 資料繫結來完成這樣的效果,底下為這個頁面的 View & ViewModel。
這個專案的原始碼你可以在這裡取得 : https://github.com/vulcanlee/XFExchange/tree/master/XFRadialMenu
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage 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"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFRadialMenu.Views.MainPage"
             Title="MainPage">
    <Grid
        HorizontalOptions="Fill" VerticalOptions="Fill"
        Margin="0,0,0,0"
        >
        <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
            <Label Text="{Binding Title}" />
            <Entry Placeholder="Account" />
            <Entry Placeholder="Password" />
            <Button Text="Login" />
        </StackLayout>

        <Grid
            HorizontalOptions="End" VerticalOptions="Center"
            RowSpacing="0" ColumnSpacing="0"
            >
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>

            <BoxView
                IsVisible="{Binding ShowMenu}"
                Grid.RowSpan="3" Grid.ColumnSpan="3"
                Color="Pink"
                 />

            <Button 
                Grid.Row="1" Grid.Column="1"
                BackgroundColor="Navy"
                TextColor="White"
                Text="Menu" Command="{Binding MenuCommand}" />

            <Button 
                IsVisible="{Binding ShowMenu}"
                Grid.Row="0" Grid.Column="0"
                Text="Sub-Menu1" Command="{Binding SubMenuCommand}" CommandParameter="Sub-Menu1" />
            <Button 
                IsVisible="{Binding ShowMenu}"
                Grid.Row="0" Grid.Column="1"
                Text="Sub-Menu2" Command="{Binding SubMenuCommand}" CommandParameter="Sub-Menu2"/>
            <Button 
                IsVisible="{Binding ShowMenu}"
                Grid.Row="0" Grid.Column="2"
                Text="Sub-Menu3" Command="{Binding SubMenuCommand}" CommandParameter="Sub-Menu3"/>
            <Button 
                IsVisible="{Binding ShowMenu}"
                Grid.Row="1" Grid.Column="0"
                Text="Sub-Menu4" Command="{Binding SubMenuCommand}" CommandParameter="Sub-Menu4"/>
            <Button 
                IsVisible="{Binding ShowMenu}"
                Grid.Row="1" Grid.Column="2"
                Text="Sub-Menu5" Command="{Binding SubMenuCommand}" CommandParameter="Sub-Menu5"/>
            <Button 
                IsVisible="{Binding ShowMenu}"
                Grid.Row="2" Grid.Column="0"
                Text="Sub-Menu6" Command="{Binding SubMenuCommand}" CommandParameter="Sub-Menu6"/>
            <Button 
                IsVisible="{Binding ShowMenu}"
                Grid.Row="2" Grid.Column="1"
                Text="Sub-Menu7" Command="{Binding SubMenuCommand}" CommandParameter="Sub-Menu7"/>
            <Button 
                IsVisible="{Binding ShowMenu}"
                Grid.Row="2" Grid.Column="2"
                Text="Sub-Menu8" Command="{Binding SubMenuCommand}" CommandParameter="Sub-Menu8"/>
        </Grid>
    </Grid>
</ContentPage>
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;

namespace XFRadialMenu.ViewModels
{
    public class MainPageViewModel : BindableBase, INavigationAware
    {
        private string _title;
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        #region ShowMenu
        private bool _ShowMenu=false;
        /// <summary>
        /// ShowMenu
        /// </summary>
        public bool ShowMenu
        {
            get { return this._ShowMenu; }
            set { this.SetProperty(ref this._ShowMenu, value); }
        }
        #endregion

        public DelegateCommand MenuCommand { get; set; }

        public DelegateCommand<string> SubMenuCommand { get; set; }

        public MainPageViewModel()
        {
            MenuCommand = new DelegateCommand(() =>
            {
                ShowMenu = !ShowMenu;
            });
            SubMenuCommand = new DelegateCommand<string>(x =>
            {
                Title = $"Your press {x}";
                ShowMenu = false;
            });
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {

        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {
            if (parameters.ContainsKey("title"))
                Title = (string)parameters["title"] + " and Prism";
        }
    }
}