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!!


<<:  Day11 Sideproject(作品集) from 0 to 1 - docker化前端篇

>>:  [Day10]资讯管理系统框架 - 高阶系统框架

Day 06-大 module 小 module,能够重复使用又好维护的就是好 module

大 module 小 module,能够重复使用又好维护的就是好 module 上一章介绍 modu...

连续 30 天 玩玩看 ProtoPie - Day 23

今天来玩这个,模拟一个旋转钮。 (其实是 Slider 但这东西真不容易翻译。等等直接看图片吧。) ...

Day 11 : PHP - 如何将HTML的内容传送到PHP?POST和GET又该如何选择?

这篇想和大家介绍如何将HTML的内容传送到PHP 因为HTML呈现的是网页的画面,若想做些运算或储存...

Java 开发 WEB 的好平台 -- Grails -- (4) 建立第一个 Controller

在Grails 里建立 controller 是一件很愉快、简单的事情。基本上,你无须使用任何 an...

Day29 Mixin

当元件之间共用方法时就可以使用组件,所有元件的选项都可以使用,当使用mixin时,mixin中的选将...