WPF,如何使用MVVM模式触发ListBox.ScrollIntoView?

时间:2019-01-22 00:33:31

标签: c# wpf xaml mvvm

我有一个WPF应用程序,当用户按下按钮时,ListBox的内容就会更新。我最初的问题是将ListBox重新聚焦到特定的SelectedIndex值,该值绑定到ViewModel中的ActiveItem属性。我可以使用以下代码解决此问题:

XAML:

flush_in(stdin)

隐藏代码:

<ListBox ItemsSource="{Binding ListOfItems}" SelectedIndex="{Binding ActiveItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                 IsSynchronizedWithCurrentItem="True"  SelectionChanged="ListBox_SelectionChanged" x:Name="ListBoxSelector">

但是,我目前在MainWindow.xaml.cs文件而不是ViewModel中具有以上代码。我的问题是如何将这段代码移至ViewModel,以便坚持使用MVVM模式?我不太清楚如何从ViewModel中正确处理ListBox的ScrollIntoView属性。

4 个答案:

答案 0 :(得分:1)

您可以使用Behavior类强制选定的项目滚动到视图中。

public class perListBoxHelper : Behavior<ListBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
        base.OnDetaching();
    }

    private static void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var listBox = sender as ListBox;

        if (listBox?.SelectedItem == null)
            return;

        Action action = () =>
        {
            listBox.UpdateLayout();

            if (listBox.SelectedItem != null)
                listBox.ScrollIntoView(listBox.SelectedItem);
        };

        listBox.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle);
    }
}

有关我的blog post的更多详细信息。

此外,我个人将绑定到ListBox的SelectedItem而不是SelectedIndex,并在该属性设置器中处理对项目选择的任何处理,而不是使用事件处理程序。

答案 1 :(得分:0)

MVVM模式不排除使用后面的代码。实际上,这不可能,因为在某些情况下,背后的代码是正确的做法。视图模型是一个模型,不是视图替换。考虑它的另一种方法是,视图模型包含内容,而视图包含方式。至少,这是我对MVVM模式的解释。

在您的情况下,什么是项目列表和当前项目。 how ListBox本身及其默认行为。在我看来,将选定的项目滚动到视图中是一种额外的行为,因此应保留在视图中。您不会违反MVVM模式,因为您将内容保留在视图模型中,并将 how 保留在视图中。

答案 2 :(得分:0)

我不确定我的解决方案是否是MVVM模式。但是对于这种问题,它可以解决此问题。

这是我要做的:如果按下Button,它将触发一个命令调用ViewModel中的方法。当ViewModel完成其工作时,viewModel会引发一个自定义事件(其中包括项目索引,列表框应滚动到该事件)。并且在发生这种情况之前,加载View时,View的Code-behind应该通过View的DataContext侦听其ViewModel,然后执行scrollIntoView。

正如我所说,我不确定这是否是MVVM,但是我认为这是可以接受的。

答案 3 :(得分:0)

没有针对每个请求的通用解决方案,正如其他人提到的那样,MVVM并不意味着没有代码,但也没有多余的代码。

但是,如果您不想要任何代码,则可以在您的特定请求中找到解决方案-创建一个继承自ListView的类并按需要处理请求,然后在XAML中使用它。 / p>