學習目標
- 整段 Section 隱藏和顯示的方法
- Table 也可以當作 Menu 使用!
接續前一小節,我們有個簡單的功能還未完成,
就是開啟 Programmer switch 開關時,才能去點選 Language 和 Platform 這兩個屬性,反之則不能點選。
要完成這個功能,我們要藉由 TableView 本身能放置多組的 TableSection 的特性,並直接隱藏或顯示整組 TableSection
然而...隱藏 TableSection 這件事 無法用 XAML 處理,需借助 C# 才能完成...
接續上一小節的範例,
但我們將 Language 和 Platform 這兩個 PickerCell,移放到一個新的 TableSection 內:
ConditionalSection
*OnPlatform 寫法已更改,請參考此篇文章
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:ConditionalSection" xmlns:toolkit="clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit" x:Class="ConditionalSection.ConditionalSectionPage"> <ContentPage.Padding> <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" /> </ContentPage.Padding> <StackLayout> <TableView x:Name="tableView" Intent="Form"> <TableRoot Title="Data Form"> <TableSection Title="Personal Information"> <EntryCell Label="Name:" Text="{Binding Name}" Placeholder="Enter name" Keyboard="Text" /> <EntryCell Label="Email:" Text="{Binding EmailAddress}" Placeholder="Enter email address" Keyboard="Email" /> <EntryCell Label="Phone:" Text="{Binding PhoneNumber}" Placeholder="Enter phone number" Keyboard="Telephone" /> <toolkit:PickerCell Label="Age Range:" Title="Age Range" SelectedValue="{Binding AgeRange}"> <x:String>10 - 19</x:String> <x:String>20 - 29</x:String> <x:String>30 - 39</x:String> <x:String>40 - 49</x:String> <x:String>50 - 59</x:String> <x:String>60 - 99</x:String> </toolkit:PickerCell> <SwitchCell x:Name="isProgrammerSwitch" Text="Are you a programmer?" On="{Binding IsProgrammer}" /> </TableSection> <!-- 新增一個 TableSection--> <TableSection x:Name="programmerInfoSection" Title="Programmer Information"> <toolkit:PickerCell Label="Language:" Title="Language" SelectedValue="{Binding Language}"> <x:String>C</x:String> <x:String>C++</x:String> <x:String>C#</x:String> <x:String>Objective C</x:String> <x:String>Java</x:String> <x:String>Other</x:String> </toolkit:PickerCell> <toolkit:PickerCell Label="Platform:" Title="Platform" SelectedValue="{Binding Platform}"> <x:String>iPhone</x:String> <x:String>Android</x:String> <x:String>Windows Phone</x:String> <x:String>Other</x:String> </toolkit:PickerCell> </TableSection> </TableRoot> </TableView> </StackLayout> </ContentPage>
.cs 控制 programmerInfoSection 的隱藏或顯示:
public partial class ConditionalSectionPage : ContentPage { public ConditionalSectionPage() { InitializeComponent(); // 設定 tableView 的 BindingContext ProgrammerInformation programmerInfo = new ProgrammerInformation(); tableView.BindingContext = programmerInfo; // 先將要控制的 TableSection 移除 tableView.Root.Remove(programmerInfoSection); // 等待 IsProgrammer 屬性更改時. programmerInfo.PropertyChanged += (sender, args) => { if (args.PropertyName == "IsProgrammer") { if (programmerInfo.IsProgrammer && tableView.Root.IndexOf(programmerInfoSection) == -1) { // 將 TableSection 加入 TableView tableView.Root.Add(programmerInfoSection); } if (!programmerInfo.IsProgrammer && tableView.Root.IndexOf(programmerInfoSection) != -1) { // 移除 TableSection tableView.Root.Remove(programmerInfoSection); } } }; } }
可以注意一下 programmerInfo.PropertyChanged += 第 15 行,屬性發生改變時的事件 這寫法,
第一次看到這個寫法覺得滿新奇的... 原來 Xamarin 可以這樣寫...
執行結果:
switch 關閉
switch 開啟
* 貼心提醒:每個 TableSection 都可以擁有 自己的 BindingContext 喔!
* 可以發現 windows 沒有作用...
TableView Menu
這功能算是... TableView 的變化吧,
我們將 TableView 的 Cell 都只放置事件就好,很簡單的就可以形成一個選單了...
這就是為什麼 TextCell 和 ImageCell 會有 Command 和 CommandParameter 屬性,想當然可以將之綁定於寫好的 commands,執行我們要做的事件,或是導覽去別的頁面。
底下來看範例,TableView 有四個 TextCell,分別可以控制 BoxView 左、上、右、下 移動
*OnPlatform 寫法已更改,請參考此篇文章
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MenuCommands.MenuCommandsPage" x:Name="page"> <ContentPage.Padding> <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" /> </ContentPage.Padding> <StackLayout> <TableView Intent="Menu" VerticalOptions="Fill" BindingContext="{x:Reference page}"> <TableRoot> <TableSection Title="Move the Box"> <!--綁定 MoveCommand 並傳入參數--> <TextCell Text="Left" Command="{Binding MoveCommand}" CommandParameter="left" /> <TextCell Text="Up" Command="{Binding MoveCommand}" CommandParameter="up" /> <TextCell Text="Right" Command="{Binding MoveCommand}" CommandParameter="right" /> <TextCell Text="Down" Command="{Binding MoveCommand}" CommandParameter="down" /> </TableSection> </TableRoot> </TableView> <AbsoluteLayout BackgroundColor="Maroon" VerticalOptions="FillAndExpand"> <BoxView x:Name="boxView" Color="Blue" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0.5, 0.5, 0.2, 0.2" /> </AbsoluteLayout> </StackLayout> </ContentPage>
.cs
值得一提的是,ContentPage 的 BindingContext 就是自己,所以可以直接綁定自己 .cs 內的 Command。
public partial class MenuCommandsPage : ContentPage { int xOffset = 0; // ranges from -2 to 2 int yOffset = 0; // ranges from -2 to 2 public MenuCommandsPage() { // 初始化 Command MoveCommand = new Command(ExecuteMove, CanExecuteMove); InitializeComponent(); } public ICommand MoveCommand { private set; get; } void ExecuteMove(string direction) { switch (direction) { case "left": xOffset--; break; case "right": xOffset++; break; case "up": yOffset--; break; case "down": yOffset++; break; } ((Command)MoveCommand).ChangeCanExecute(); // 移動 boxView 在 AbsoluteLayout 內的位置 AbsoluteLayout.SetLayoutBounds(boxView, new Rectangle((xOffset + 2) / 4.0, (yOffset + 2) / 4.0, 0.2, 0.2)); } bool CanExecuteMove(string direction) { // 當碰到邊界時就不能再移動 switch (direction) { case "left": return xOffset > -2; case "right": return xOffset < 2; case "up": return yOffset > -2; case "down": return yOffset < 2; } return false; } }
執行結果:
*當然,也可以放在 master/detail page 內作為選單使用。
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。