XAML in Xamarin.Forms 基礎篇 電子書

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

Xamarin.Forms 快速入門 電子書

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

2017/02/23

Xamarin Cycle 9: 準備注意事項說明

今日,2017.03.23 可以更新到 Xamarin Cycle 9 這個版本,這個版本將會支援 iOS 10.4 & Android 7.1
請參考底下說明,將您的開發環境,調整成為此篇文章說明內容

請安裝 JDK 1.8 x64 版本

現在最新的 JDK 1.8 版的為 8u121

升級 Visual Studio 2015 使用的 Xamarin Toolkit 到 4.3 版本

  • 點選 Visual Studio 2015 功能表 工具 > 選項 > Xamarin > Other > Stable > Check Now
  • 下載完成後,請點選安裝按鈕
  • 今日更新完成後的 Xamarin Toolkit 版本資訊

確認 Xamarin.Android 有使用最新安裝的 JDK

  • 點選 Visual Studio 2015 功能表 工具 > 選項 > Xamarin > Android
  • 找到 Java 開發套件位置,點選變更,切換到 x64 JDK 1.8.0.121 的安裝位置
    C:\Program Files\Java\jdk1.8.0_121

確認 Android SDK 都有安裝與升級到最新版本

  • 點選 Visual Studio 2105 功能表 工具 > Android > Android SDK Manager
  • 確定底下指出的套件,都有安裝與升級到最新版本
    • Tools > Android SDK Tools 25.2.5
    • Tools > Android SDK Platform-tools 25.0.3
    • Tools > Android SDK Build-Tools 25.0.2
    • Android 7.1.1(API 25) > SDK Platform
    • Android 7.0(API 24) > SDK Platform
    • Android 6.0(API 23) > SDK Platform
    • Android 5.1.1(API 22) > SDK Platform
    • Android 5.0.1(API 21) > SDK Platform
    • Android 4.4W.2(API 20) > SDK Platform
    • Android 4.4.2(API 19) > SDK Platform
    • Extras > Android Support Repository 44
    • Extras > Google USB Driver 11

Mac 電腦上也需要同步更新

若您有開發 iOS App,請記得上述的步驟,也需要在 Mac 電腦上都要做一次。
在 Mac 電腦上,您需要更新 Xamarin Studio 到最新版本

2017/02/20

Xamarin FAQ 2-20 : 在ListView中,如何實作出下拉更新的手勢操作

問題

Xamarin.Forms 的 ListView 是否有支援手勢更新的功能,也就是說,當使用者在 ListView 最前面的紀錄是第一筆紀錄的時候,可以使用手指由上往下滑動 ListView,如此,就可以即時更新到最新的資料。

解答

首先,我們先來建立一個頁面,裡面有個 ListView 控制項,看看有那些地方是需要設定的。
在下方的 ListView 標機宣告中,我們使用了
  • IsPullToRefreshEnabled="True"
    設定這個 ListView 需要啟用下拉更新的手勢操作
  • RefreshCommand="{Binding ListView更新資料Command}"
    當 ListView 偵測到您有下拉更新的手勢操作行為時候,這個 RefreshCommand 所綁定的命令,將會被執行;在這個 ICommand 命令中,我們將會更新 DataItemList 的集合資料內容
  • IsRefreshing="{Binding IsBusy}"
    IsRefreshing 將會顯示一個忙碌中的視覺,讓使用者知道 ListView 正在更新資料中,不過,當更新完成資料後,將會設定 IsBusy 的值為 False,這樣,忙碌中的視覺就不會出現了。
<?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="XFListViewRefresh.Views.MainPage"
             Title="ListView下拉更新">

    <StackLayout 
      Margin="20"
      HorizontalOptions="Fill" VerticalOptions="Fill">
        <Label Text="{Binding Title}" />
        <ListView
            HorizontalOptions="Fill" VerticalOptions="FillAndExpand"
            ItemsSource="{Binding DataItemList}"
            IsPullToRefreshEnabled="True"
            HasUnevenRows="True"
            RefreshCommand="{Binding ListView更新資料Command}"
            IsRefreshing="{Binding IsBusy}"
            >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid
                            RowSpacing="0" ColumnSpacing="0"
                            >
                            <Label Text="{Binding DataVale}" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>
要進行下拉更新命令的時候,可以類似底下的處理動作。
            ListView更新資料Command = new DelegateCommand(() =>
            {
                IsBusy = true;
                Refresh();
                IsBusy = false;
            });
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin Button 的 Command / CommandParameter 綁定與 IsEnabled 的問題測試

在這個範例中,我們需要來進行測試這個需求:
對於 Button 按鈕,我們需要使用 Command 來綁定 ViewModl 上的 ICommand 的物件,並且需要使用 CommandParameter 取得當時綁定的物件內容,而且,需要使用 ViewModel 內的某個屬性,綁定到這個按鈕上的 IsEnabled 屬性,這是要做到可以透過 ViewModel 來控制這個按鈕是否可以使用。
不過,在 Xamarin.Forms 中,若您是在底下的情境,上述的動作將會失敗。
這在這使用情境中,我們使用了 Source 來指定需要綁定物件的來源,並且,CommandParameter 使用了 Binding . 來綁定當時的物件;在這個情況之下,這個 XAML 中的 IsEnable 屬性綁定就會失敗,這個屬性值永遠為 True。
        <Button 
            Text="3 命令綁定、CmdPara(.)、Source"
            Command="{Binding Path=BindingContext.按鈕命令綁定測試Command, Source={x:Reference ThisPage}}"
            CommandParameter="{Binding .}"
            IsEnabled="{Binding 按鈕命令綁定測試狀態}"/>
想要解決這個問題,需要使用 System.Windows.Input.ICommand 提供的 CanExecute 委派方法來解決。

專案原始碼

執行範例

2017/02/19

Xamarin FAQ 2-19 : 在ListView中,如何根據紀錄類型,顯示出不同的樣貌(資料樣板選擇器)

問題

在 Xamarin.Forms中,有個 DataTemplateSelector (資料樣板選擇器),請問這是甚麼類別,用來做甚麼用途的呢?

解答

測試範例專案原始碼
在ListView中,若我們想要根據紀錄類型,顯示出不同的樣貌,此時,並不是在 ViewModel 中做處理,而是我們是先定義了多個資料樣板,我們想要透過 DataTemplateSelector (資料樣板選擇器)來根據當時的資料內容,自動幫我們選擇合適的資料樣板;如此,ListView 就可以根據每筆紀錄的內容,顯示出不同的視覺效果了。
在底下的 XAML 範例中,我們在 ContentPage.Resources 中定義了兩個資料樣板 validPersonTemplate / invalidPersonTemplate,另外,也宣告了一個 local:PersonDataTemplateSelector 物件,這個物件是我們自行定義的一個類別,用來根據當時的資料內容,自動傳回合適的資料樣板。
<?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:local="clr-namespace:XFSelector"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFSelector.Views.HasSelectorPage">

    <ContentPage.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="validPersonTemplate">
                <ViewCell>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="0.4*" />
                            <ColumnDefinition Width="0.3*" />
                            <ColumnDefinition Width="0.3*" />
                        </Grid.ColumnDefinitions>
                        <Label Text="{Binding Name}" TextColor="Green" FontAttributes="Bold" />
                        <Label Grid.Column="1" Text="{Binding DateOfBirth, StringFormat='{0:d}'}" TextColor="Green" />
                        <Label Grid.Column="2" Text="{Binding Location}" TextColor="Green" HorizontalTextAlignment="End" />
                    </Grid>
                </ViewCell>
            </DataTemplate>
            <DataTemplate x:Key="invalidPersonTemplate">
                <ViewCell>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="0.4*" />
                            <ColumnDefinition Width="0.3*" />
                            <ColumnDefinition Width="0.3*" />
                        </Grid.ColumnDefinitions>
                        <Label Text="{Binding Name}" TextColor="Red" FontAttributes="Bold" />
                        <Label Grid.Column="1" Text="{Binding DateOfBirth, StringFormat='{0:d}'}" TextColor="Red" />
                        <Label Grid.Column="2" Text="{Binding Location}" TextColor="Red" HorizontalTextAlignment="End" />
                    </Grid>
                </ViewCell>
            </DataTemplate>
            <local:PersonDataTemplateSelector 
                x:Key="personDataTemplateSelector" 
                ValidTemplate="{StaticResource validPersonTemplate}" 
                InvalidTemplate="{StaticResource invalidPersonTemplate}" />
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout Padding="20">
        <Label Text="有使用資料樣板選擇器" FontAttributes="Bold" HorizontalOptions="Center" />
        <ListView 
            ItemsSource="{Binding People}"
            ItemTemplate="{StaticResource personDataTemplateSelector}" />
    </StackLayout>
</ContentPage>
接下來,我們來看看 PersonDataTemplateSelector 這個類別要如何定義呢?首先,需要繼承 DataTemplateSelector 這個類別,並且要定義 OnSelectTemplate 這個方法,而我們就會在 OnSelectTemplate 這個方法內,依據當時紀錄的內容,決定要使用哪個資料樣板。
    /// <summary>
    /// 依據出生日期年分,決定要顯示哪種資料樣板
    /// </summary>
    public class PersonDataTemplateSelector : DataTemplateSelector
    {
        // 這個物件值,將會在 XAML 中來定義
        public DataTemplate ValidTemplate { get; set; }

        // 這個物件值,將會在 XAML 中來定義
        public DataTemplate InvalidTemplate { get; set; }

        protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
        {
            // 根據當時物件的值,決定要使用哪個資料樣板
            return ((Person)item).DateOfBirth.Year >= 1980 ? ValidTemplate : InvalidTemplate;
        }
    }
Xamarin-跨平台手機應用程式設計入門-粉絲團