MVVM模式 - 执行视图操作

时间:2013-05-08 16:49:27

标签: wpf xaml mvvm windows-8 mvvm-light

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

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

2 个答案:

答案 0 :(得分:1)

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

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

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

是的,事件是理想的方法,以避免在ViewModel中引用View。不过我建议在ViewModel中创建一个自定义事件(例如OnFirstItemInViewChanged,其中包含要滚动到的项的参数),并在View事件代码隐藏寄存器中创建此事件,然后调用ListView.ScrollIntoView(item)。

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

答案 1 :(得分:1)

使用EventHandlerScrollIntoView(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);
}

这就是我通常对每个案例进行一些调整的方法。