XAML in Xamarin.Forms 基礎篇 電子書

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

Xamarin.Forms 快速入門 電子書

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

2019/04/22

Xamarin.Forms 之 XAML 設計預覽的設計時期資料

Xamarin.Forms 之 XAML 設計預覽的設計時期資料

在前一篇文章 Xamarin.Forms 之 XAML 設計預覽 有說明,如何在 Visual Studio 2019 下,使用頁面預覽的功能,以便在進行 XAML 語言設計過程中,可以即時看到這些設計後的執行結果。

了解更多關於 [Xamarin.Android] 的使用方式
了解更多關於 [Xamarin.iOS] 的使用方式
了解更多關於 [Xamarin.Forms] 的使用方式
了解更多關於 [Hello, Android:快速入門] 的使用方式
了解更多關於 [Hello, iOS – 快速入門] 的使用方式
了解更多關於 [Xamarin.Forms 快速入門] 的使用方式
現在遇到一個問題,那就是通常在進行 XAML 設計的時候,都會使用 資料綁定 Data Binding 手法,與該頁面的 ViewModel 進行綁定再一起,可是,當使用這樣的設計方式的時候,又想要使用設計時期預覽功能,就會發現到有許多內容,還是需要在執行時期的時候,才能夠看到該頁面的執行結果。
為了解決這樣的問題,需要使用所謂的 [設計時期資料] 這樣的機制,需要使用 Xamarin.Forms 提供的新功能,首先,需要在 ContentPage 內加入底下的命名空間宣告,有了這些宣告,才能夠在 XAML 中使用設計時期資料的功能。
xaml
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
現在,可以將 MainPage.xaml 的內容修正成為如下所示,其中對於 Label Text="{Binding Message}" />這個 XAML 標記,由於使用資料綁定來宣告,因此,這樣的用法只能夠在該專案執行的時候,才能夠看到該文字標籤顯示的內容;若想要在設計時期指定該 Label 這個文字標籤的 Text 屬性值,則需要使用 d: 這個命名空間來指定設計時期的屬性名稱,指定該設計時期的屬性值內容,如此,才能夠在設計階段在預覽畫面上看到這些內容,在此,要使用 <Label Text="{Binding Message}" d:Text="這是設計時期指定資料"/> 這樣的宣告語法。從下圖將會看到該 XAML 所指定的設計時期的資料值顯示情況。
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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="BlankApp5.Views.MainPage"
             Title="{Binding Title}">

    <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
        <Label Text="Welcome to Xamarin Forms and Prism!" />
        <Label Text="{Binding Message}" />
        <Label Text="{Binding Message}" d:Text="這是設計時期指定資料"/>
        <BoxView Color="Blue" d:Color="Red"/>
    </StackLayout>

</ContentPage>
可是,這個頁面在執行時期,將會顯成為這樣的情況,從這兩個畫面,可以看到當初指定在設計時期的 XAML 屬性值,是沒有影響到執行時期的 XAML 屬性值。
然而,對於像是 ListView 這樣的檢視,需要指定一個集合紀錄物件給 ItemsSource 這個使用,當然,最為方便的方式還是使用 ViewModel 來建立這樣的物件,並且透過資料綁定的方式指定給 ListView。
首先,在 ContentPage 內加入一個 XAML 命名空間,該命名空間將會指向該頁面的 ViewModel,在此,將會使用 xmlns:ViewModel="clr-namespace:BlankApp5.ViewModels" 這樣的宣告語法。接著,可以在該頁面內,使用 d: 命名空間,指定設計時期的該頁面之 BindingContext 屬性值,指向為 MainPageViewModel。
xaml
    <d:ContentPage.BindingContext>
        <ViewModel:MainPageViewModel/>
    </d:ContentPage.BindingContext>
不過,這樣又產生一個問題,那就是原有的 ViewModel 類別中,沒有預設建構式存在,而會得到 : XLS0507 類型 'MainPageViewModel' 無法用做為物件元素,因為它並非公用,或是未定義公用的無參數建構函式或類型轉換子 這樣的錯誤訊息。
因此,需要在 MainPageViewModel 類別中加入一個預設建構式,並且把 XAML 頁面修改成為底下的宣告,如此,就可以在設計時期,使用 Visual Studio 2019 的頁面預覽功能,看到 ListView 的設計時期呈現的樣貌了。
底下是執行螢幕截圖
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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             xmlns:ViewModel="clr-namespace:BlankApp5.ViewModels"
             x:Class="BlankApp5.Views.MainPage"
             Title="{Binding Title}">

    <d:ContentPage.BindingContext>
        <ViewModel:MainPageViewModel/>
    </d:ContentPage.BindingContext>

    <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
        <Label Text="Welcome to Xamarin Forms and Prism!" />
        <Label Text="{Binding Message}" />
        <Label Text="{Binding Message}" d:Text="這是設計時期指定資料"/>
        <BoxView Color="Blue" d:Color="Red"/>
        <ListView
            ItemsSource="{Binding myItemList}"
            >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Label Text="{Binding Name}"
                               FontSize="20"/>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>

</ContentPage>
C Sharp / C#
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BlankApp5.ViewModels
{
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using Prism.Events;
    using Prism.Navigation;
    using Prism.Services;
    public class MyModel : INotifyPropertyChanged
    {
        public string Name { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
    }
    public class MainPageViewModel : INotifyPropertyChanged, INavigationAware
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string Message { get; set; }
        public ObservableCollection<MyModel> myItemList { get; set; } = new ObservableCollection<MyModel>();
        private readonly INavigationService navigationService;

        public MainPageViewModel()
        {
            Message = "Come From Default Constuctor  !!";
            myItemList.Add(new MyModel() { Name = "張三" });
            myItemList.Add(new MyModel() { Name = "李四" });
            myItemList.Add(new MyModel() { Name = "王五" });
        }

        public MainPageViewModel(INavigationService navigationService)
        {
            this.navigationService = navigationService;
            Message = "Come From Injection Constructor";
            myItemList.Add(new MyModel() { Name = "張三A" });
            myItemList.Add(new MyModel() { Name = "李四B" });
            myItemList.Add(new MyModel() { Name = "王五C" });
        }

        public void OnNavigatedFrom(INavigationParameters parameters)
        {
        }

        public void OnNavigatedTo(INavigationParameters parameters)
        {
        }

        public void OnNavigatingTo(INavigationParameters parameters)
        {
        }

    }
}



沒有留言:

張貼留言