1

我正在使用 MVVM Pattern(带有 MVVM Light)来构建我的 XAML 应用程序(win8)。我有一个 ListView,它绑定到我的 ViewModel 的一个属性。我还有一个按钮可以触发对该 ViewModel 的操作,该操作会更新该属性(这会导致更新 ListView)。该按钮使用命令对 ViewModel 执行操作。到目前为止,一切都很好。

问题是刷新列表后,我需要执行严格属于我的视图的操作,而不是视图模型。它应该将列表滚动到特定项目。如何触发该操作?我应该使用特定的 ListView 事件吗?

4

2 回答 2

1

ViewModel 用于将 UI 代码与 UI 设计(例如 XAML)分离。【设计师和开发者的关注点分离,UI代码的自动化测试等】

理想情况下,View 的代码隐藏文件将为空(对 InitializeComponent 的调用除外),所有 UI 逻辑和状态都将由 ViewModel 处理。但是,在实践中,可能有一些特定的 UI 操作无法单独通过数据绑定处理,您将需要求助于代码。这样的代码应该放在代码隐藏中。

在您的情况下,(a)何时和(b)滚动到哪个项目的逻辑必须在 ViewModel 中(而不是在 View 中)。只有在 ListView 中执行实际滚动所需的任何附加逻辑才会在 View 代码隐藏中。

是的,事件将是执行此操作的理想方式,以避免在 ViewModel 中对视图有任何引用。但是,我建议在 ViewModel 中创建一个自定义事件(例如 OnFirstItemInViewChanged 和要滚动到的项目的参数),并在 View 代码隐藏中注册到该事件并调用 ListView.ScrollIntoView(item)。

注意:WinForms DataGridView 有一个属性 FirstDisplayedScrollingRowIndex。如果 WPF ListView 中有类似的东西,您可以通过将此属性绑定到 ViewModel 属性来解决此问题,从而使代码隐藏完全干净。

于 2013-05-08T17:48:02.837 回答
1

使用EventHandlerandScrollIntoView(Object)方法,您可以在不使用 ViewMovel 中的 View 引用并尊重 MVVM 模式的情况下实现您想要的。

在您的 ViewModel 中创建一个事件,如下所示:

public event EventHandler ScrollListView;

ListView在您的视图中添加一个回调以在属性更新时滚动:

ViewModel vm;
vm.ScrollListView += (sender, e) =>
{
     var specificItem = **some item**;
     MyListView.SelectedItem = specificItem; 
     MyListView.UpdateLayout();
     MyListView.ScrollIntoView(MyListView.SelectedItem);
};

然后在您的 ViewModel 中,当您更新该属性并想要滚动时ListView

if (this.ScrollListView != null)
{
    this.ScrollListView(this, EventArgs.Empty);
}

当然,这就是我通常对每种情况进行一些调整的方式。

于 2013-05-08T17:50:17.430 回答