iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Mobile Development

Re: 從零開始用 Xamarin 技術來復刻過去開發的一個 App : TopStore系列 第 17

EP 17: The MenuItem of ListView binds Command in ViewModel - Way 2

Hello, 各位 iT邦幫忙 的粉絲們大家好~~~

本篇是 Re: 從零開始用 Xamarin 技術來複刻過去開發的一個 App: TopStore 系列文的 EP17。

在本系列的 EP14 當中已經能讓使用者在 PeoplePage 在 ListView 當中,透過點選設計在 ViewCell.ContextActions 的 "MenuItem 刪除",並且透過 Binding(繫結) 自行設計的 Command 的方式,來完成 PeoplePage 當中的一筆聯絡人資料從聯絡人列表當中刪除。

在本系列的 EP16 當中則是透過設計讓使用者在 PeoplePage 點選聯絡人列表的 ListView 當中某筆聯絡人的 "刪除",觸發 該 "MenuItem 刪除" 的 Clicked 所註冊的透過事件處理常式,並透過事件處理常式呼叫執行 PeoplePageViewModel 的 DeleteCommad,進而執行刪除聯絡人的執行。

接下來本回 EP17 要來討論一個問題,除了像是在 EP14 設計的給 "MenuItem 刪除" 所 Binding (繫結)到的 DeleteCommand,其 DeleteCommand 的撰寫是在 Models 底下的 Person 類別當中;而 EP16 透過事件觸發轉而執行 ViewModel 當中設計的 Command,這兩種方式之外,是否能做到 "類似" 於透過 EP15 當中 "Button 打電話" 處理作法來完成呢?

目前的答案是 "有的",不然本篇 EP17 也寫不下去了,哈哈~~~

所以該怎麼調整,讓該 Command 能放在該頁面所設計的 ViewModel ,並且又能透過 MenuItem 的 Command 直接 Binding (繫結)到呢?

那我們就開始囉!!!


或許有朋友已經猜到是否如 EP15 之法炮製就可以呢? 理論上應該要可以,但現實很骨感的..."不行"。

這問題到底是算誰的錯其實 "短期" 內也說不準,目前在 Xamarin.Forms 的官方 GitHub Repo 底下有一個相關的 issue 被回報成 [Bug] 持續的 Open 中,也沒有進一步的得到回應或處理,所以短時間內就先放下這個想法吧!

或許有先進同好可以幫忙處理,那也請到該 issue 來回覆相關的解決方式,讓大家都能獲得一個身心靈上的慰藉...XD

Xamarin.Forms: [Bug] RelativeSource not working for MenuItem #12629
Xamarin.Forms: [Bug] RelativeSource not working for MenuItem #12629

所以山不轉路轉,本篇 EP17 換個方式來處理,也還是能達成所要的目的!

首先打開 PeoplePage.xmal,找到 EP16 當初修改成 Clicked 事件註冊的 XAML 撰寫,然後..."刪掉"!
MenuItem 的 Clicked 事件註冊的 XAML 刪除 1

MenuItem 的 Clicked 事件註冊的 XAML 刪除 2

如果覺得 PeoplePage.xaml.cs 當中在 EP16 所撰寫的事件處理常式很雞肋的話,一樣也可以 "刪掉" 了...
MenuItem 的 Clicked 事件處理常式刪除 1

MenuItem 的 Clicked 事件處理常式刪除 2

接著撰寫其 MenuItem 的 Command 與 CommandParameter 指定。
MenuItem 的 Command 與 CommandParameter 的指定

其中注意到...

在指定 Command 的 Binding 行為當中,特別設定其 Source 是透由 x:Reference 來取得 Binding(繫結) 到對應的 UI 元件而完成的。
MenuItem 的 Command 指定其 Binding 的 Source 設定值為 x:Reference

而其 Command 的 Path 設定則為找到該 UI 元件其 BindingContext 是 PeoplePageViewModel 之物件即可執行其撰寫的 DeleteCommand。
PeoplePageViewModel 撰寫的 DeleteCommand

那...其 CommandParameter 的部分就不說了,設計原理跟 EP15 所談到的概念就是一樣的了。

最後,就決定一個替死鬼 UI 元件其 BindingContext 是 PeoplePageViewModel 的物件,並設計其 UI 元件的名稱即可解決。

在這邊既然是發生在 ListView 底下的 MenuItem 所要撰寫的 XAML,就冤有頭債有主的替 ListView 做個 x:Name 的命名吧!
ListView 的 x:Name 命名指定

接下來就試著在雙平台 (iOS、Android) 來執行看看囉。

老樣子...

針對 ListView 當中的聯絡人列表選取其中某筆聯絡人做刪除的動作。
透過 ListView 設計與處理聯絡人刪除 1

此動作會透由前面 Command 所設計的 Binding(繫結) 動作去執行 PeoplePageViewModel 所撰寫的 DeleteCommand 來執行。

執行 DeleteCommand 所設計的程式,並且出現 Alert 詢問使用者是否真的要刪除該筆聯絡人資訊。
透過 ListView 設計與處理聯絡人刪除 2

如果使用者選擇確定,則該筆資料從 MockData 的聯絡人當中刪除,並從 ListView 的畫面呈現中消失。
透過 ListView 設計與處理聯絡人刪除 3

好啦,目前改寫到 EP17 的這種處理作法,雖然沒有這麼完美(說真的應該要能像 EP15 當中的手法來完成),但至少還能透過此手法將 MVVM 框架的職責給區隔開來,並且完成 MenuItem 所賦予的執行的目的。

也不用要像 EP16 在其頁面對應的 xaml.cs 去撰寫所註冊的事件註冊常式,以減少其頁面程式的耦合性問題。

以上本 EP17 就介紹到這邊...

下篇 EP18 見囉~~~

BaBa!!


上一篇
EP 16: The MenuItem of ListView binds Command in ViewModel - Way 1
下一篇
EP 18 Search and SearchBar design in TopStore App
系列文
Re: 從零開始用 Xamarin 技術來復刻過去開發的一個 App : TopStore32

尚未有邦友留言

立即登入留言