WPF MVVM ScrollIntoView

TWT*_*TWT 5 wpf xaml listbox mvvm

我有两个列表框的视图:

列表框 1 元素:A、B、C。列表框 2 元素:...、A、...、B、...、C、...(长列表)。

当用户在列表框 1 中选择一个元素时,我想在列表框 2 中也将相同的元素滚动到视图中(而不是选择)。

在我的视图模型中,我有一个属性绑定到列表框 2 的 SelectedItem。但是如何将该元素滚动到列表框 2 的视图中?当然,我不能在我的 VM 中执行 listbox.ScrollIntoView(selectedItem)。

使用 MVVM 模式解决此问题的最佳解决方案是什么?

Mar*_*man 8

您可以通过行为来做到这一点,一个简单的解决方案根本不涉及虚拟机:

public static class ScrollToSelectedBehavior
{
    public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.RegisterAttached(
        "SelectedValue",
        typeof(object),
        typeof(ScrollToSelectedBehavior),
        new PropertyMetadata(null, OnSelectedValueChange));

    public static void SetSelectedValue(DependencyObject source, object value)
    {
        source.SetValue(SelectedValueProperty, value);
    }

    public static object GetSelectedValue(DependencyObject source)
    {
        return (object)source.GetValue(SelectedValueProperty);
    }

    private static void OnSelectedValueChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var listbox = d as ListBox;
        listbox.ScrollIntoView(e.NewValue);
    }
}
Run Code Online (Sandbox Code Playgroud)

你会像这样使用:

<ListBox x:Name="lb1" ItemsSource="{Binding Items}" />
<ListBox x:Name="lb2" ItemsSource="{Binding Items}" behaviors:ScrollToSelectedBehavior.SelectedValue="{Binding ElementName=lb1, Path=SelectedValue}"/>
Run Code Online (Sandbox Code Playgroud)

一个稍微好一点的解决方案是将行为的 DP 绑定到 VM 中的一个对象,只要 listbox1 中的选定值发生变化,该对象就会引发事件。这将向 VM 代码公开此功能,并允许进行单元测试等。