xaml - EventToCommand 与可移植 View 模型中的参数绑定(bind)

标签 xaml viewmodel mvvmcross portable-class-library eventtocommand

我正在实现一个由多个平台上的应用程序共享的 View 模型。我使用的是 MvvmCross v3,它有自己的 MvxEventToCommand 类,但我相信对于 MVVM Light 等其他框架来说,挑战是相同的。只要使用不带参数的事件,实现就很简单,对于点击控件等简单交互来说就是这种情况。

但是当命令需要处理事件参数时,事情会变得更加复杂。例如, View 模型需要对某些滚动条更改进行操作(并在关联的 ListView 中加载更多项目)。下面是 XAML 的示例:

<cmd:EventToCommand 
    Command="{Binding ScrollChanged}" 
    CommandParameter="{Binding EventArgs}" />

(MvvmCross使用MvxEventToCommand,但原理是一样的)。

然后在我的模型中我可以有以下命令处理程序:

public ICommand ScrollChanged
{
    get
    {
        return new RelayCommand<ScrollChangedEventArgs>(e =>
        {
            MessageBox.Show("Change!");
        });
    }
}

(MvvmCross 中的 MvxCommand)。

问题是 ScrollChangedEventArgs 是特定于平台的,并且此代码根本无法在可移植类库中编译。这是任何命令的普遍问题,不仅需要在事件触发时进行推送,还需要更具体的事件详细信息。将此代码移动到特定于平台的部分是愚蠢的,因为它或多或少消除了可移植 View 模型和无代码隐藏 View 的概念。我尝试搜索在不同平台之间共享 View 模型的项目,但它们都使用简单的事件,例如“Tap”,没有附加事件详细信息。

更新1 我同意 Stuart 的评论,即 View 模型应该只处理更高级别的抽象,因此我将重新表述最初的关注点:如何将低级别交互的结果映射到平台中立的结果触发业务逻辑命令的事件?考虑上面的例子:业务逻辑命令是“在列表中加载更多项目”,即我们处理列表虚拟化,其中最初加载来自大集合的有限数量的项目,并且向下滚动到列表的底部应该导致加载额外的项目。

WinRT 可以通过使用支持 ISupportIncrementalLoading 接口(interface)的可观察集合来处理列表虚拟化。当用户向下滚动列表时,运行时会检测到此功能并自动从相应的服务请求额外的项目。在其他平台上,此功能应该手动实现,除了对 ScrollViewer ScrollChanged 事件使用react之外,我找不到任何其他方法。我可以看到另外两个选项:

  • 将 OnScrollChanged 处理程序放在代码隐藏文件中,并调用可移植 View 模型更高级别的事件(例如“OnItemsRequested”);
  • 避免代码隐藏的东西并努力将 ScrollChanged 事件直接连接到 View 模型,那么我们需要首先重新映射特定于平台的事件。

只要不支持第二个选项,将事件处理程序放在代码隐藏文件中就可以,只要它的唯一目的是事件映射。但我想研究一下使用第二个选项可以做什么。 MvvmCross 有 MapCommandParameter 类,它似乎能够提供帮助,所以我想知道我是否应该利用该类。

更新 2 我尝试了 MapCommandParameter 方法,它允许我插入特定于平台的适配器,该适配器将映射低级事件以查看特定于模型的命令。所以第二个选择毫无困难地成功了。 Stuart 还建议对 ListView 进行子类化,这样就无需关心滚动事件。我打算稍后玩一下。

最佳答案

我同意 View 模型命令通常应该用 View 模型概念来表达 - 所以向 View 模型发送有关滚动条值更改的命令会很“奇怪”,但向 View 模型发送有关滚动条值更改的命令可能是可以的用户选择某些列表元素可见(她通过滚动来完成)

我之前做过此类事情的一个例子是列表选择。

我最初使用跨平台 eventargs 对象跨多个平台执行此操作 -

然后通过类似 https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.WindowsPhone/Commands/MvxSelectionChangedEventToCommand.cs 的 EventToCommand 类在 WindowsPhone 上使用它(例如)

但是...我必须承认这段代码并没有被太多使用...对于列表选择,我们主要使用selectitem绑定(bind),并且根本没有任何应用程序需要更复杂的参数化命令(到目前为止) - 您甚至可能需要返回到非常旧的 v1 mvvmcross 代码来查找使用它的任何示例。

关于xaml - EventToCommand 与可移植 View 模型中的参数绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15862285/

相关文章:

c# - Windows Phone 8.1 上的 MvvmCross 向后导航

xamarin.android - 使用后退按钮关闭 Mvvmcross 教程

xaml - UWP Light 关闭 ContentDialog

android - 使用安卓 View 模型

c# - 如何在 XAML 中将多个 StatusBarItems 对齐到右侧?

wpf - 从一个 View 模型访问另一个 View 模型的属性

c# - ListView 和枚举

xamarin.android - 如何使用 MvvmCross 框架使用 MonoDroid TabActivity

c# - 如何在代码中编辑/使用 xaml 数据模板

xaml - 是否可以绑定(bind) RelativeLayout 约束?