在MVVM(WPF)应用程序中更改ListView上的过滤器后,如何ScrollIntoView?

K J*_*K J 4 c# wpf listview filter mvvm

我在VM中有一个ObservableCollection,它显示在ListView的视图中.当所选项更改时,SelectionChanged事件将很好地触发.以下是我配置ListView的方法:

<ListView Grid.Row="3" Margin="5" AlternationCount="2" Name="_lvSettings" 
          IsSynchronizedWithCurrentItem="True"
          ItemsSource="{Binding Path=CollectionView}" 
          SelectedIndex="{Binding Path=SelectedSettingIndex}"
          SelectionChanged="OnSelectionChanged"  >
    <ListView.View>
        <GridView>
            <GridViewColumn Width="170" 
                            Header="{Binding Path=ShowAllDisplay}"
                            x:Name="_colSettings"  
                            DisplayMemberBinding="{Binding Path=Setting}"/>
            <GridViewColumn Header="Old Value" Width="150" 
                            DisplayMemberBinding="{Binding Path=OldVal}"/>
            <GridViewColumn Header="New Value" 
                            DisplayMemberBinding="{Binding Path=NewVal}" />
        </GridView>
    </ListView.View>
</ListView>
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是当我更改集合上的过滤器时.所选项目保持不变,这很好,但ListView会更改为从第一个项目显示,并且通常所选项目不在视图范围内(但仍然是所选项目).

在VM中,我有属性"SelectedSettingIndex",它在更改时抛出PropertyChanged事件.即使我提出了自己的事件手动(base.OnPropertyChanged("SelectedSettingIndex");)从虚拟机时更换过滤器,似乎事件不会真正引起人们的关注与物业并没有真正改变.必须有一个方法来调用ScrollIntoView或在这种情况下类似的东西,但我无法找出正确的事件或者触发这样做.我错过了什么?

编辑

以下是我关注的问题的一个,希望更好的描述:

1)我在VM中使用CollectionViewSource来过滤数据.

2)有一个按钮供用户在过滤器之间切换.

3)让我们假设ListView有空间在任何给定时间显示最多10个项目.

4)用户在列表视图中的索引50处的过滤视图中选择项"A".

5)然后用户单击该按钮以关闭过滤.

预期结果:ListView控件填充了未经过滤的名单,项目"A"保持选中状态,并且ListView的是"滚动",使得项目"A"仍是可见的.

实际结果:ListView中填充了未过滤的列表中,项"A"保持被选择,并且所述的ListView为"滚动"到顶部,示出第一10项.项目"A"不在视野中.

Ank*_*esh 12

如果你正在使用MVVM,那么你需要确保你已经设置了绑定到viewModel中的选定项目,并且那也是Mode=TwoWay...和滚动选择我们必须使用ListView上的行为(避免代码隐藏)

您必须添加System.Windows.Interactivity要使用的引用 Behavior<T> class

行为

public class ScrollIntoViewForListView : Behavior<ListView>
{
    /// <summary>
    ///  When Beahvior is attached
    /// </summary>
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
    }

    /// <summary>
    /// On Selection Changed
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void AssociatedObject_SelectionChanged(object sender,
                                           SelectionChangedEventArgs e)
    {
        if (sender is ListView)
        {
            ListView listview = (sender as ListView);
            if (listview.SelectedItem != null)
            {
                listview.Dispatcher.BeginInvoke(
                    (Action) (() =>
                                  {
                                      listview.UpdateLayout();
                                      if (listview.SelectedItem !=
                                          null)
                                          listview.ScrollIntoView(
                                              listview.SelectedItem);
                                  }));
            }
        }
    }
    /// <summary>
    /// When behavior is detached
    /// </summary>
    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.SelectionChanged -=
            AssociatedObject_SelectionChanged;

    }
}
Run Code Online (Sandbox Code Playgroud)

用法

将别名添加到XAMLas xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

然后在你的Control DisplayMemberBinding ="{Binding Path = Setting}"/>中

现在,当ViewModel重新选择更改时,将在列表中设置"MySelectedItem"属性时滚动.

变更通知

在viewModel中应调用已绑定到xaml的属性setter中更改的INotifyProperty,以便viewModel中的更改可以重新选择到View ...

在MVVM中使用SelectionChanged事件

同样在MVVM中,您必须使用"SelectionChnaged Event",因为您可以在Setter of MySelectedItem属性中调用函数,或者您可以使用EventToCommandclass进行显式事件调用.

过滤

Google使用ColletionViewSource进行排序,过滤等功能

希望能帮助到你...