关于c#:恢复ListView状态MVVM

Restore ListView state MVVM

当使用 MVVM 时,我们正在处理视图(而视图模型仍然存在)。

我的问题是如何在创建新视图时恢复 ListView 状态,使其尽可能接近处置视图时的状态?

ScrollIntoView 只能部分工作。我只能滚动到单个项目,它可以在顶部或底部,无法控制项目在视图中的显示位置。

我有多项选择(和水平滚动条,但这并不重要),有人可能会选择多个项目,并且可能会进一步滚动(不更改选择)。

理想情况下,将 ListView 属性中的 ScrollViewer 绑定到 viewmodel 就可以了,但我害怕遇到 XY 问题,直接要求这样做(不确定这是否适用)。此外,在我看来,这对于 wpf 来说是一件很常见的事情,但也许我无法正确制定谷歌查询,因为我找不到相关的 ListView ScrollViewer MVVM 组合。

这可能吗?

我在使用 ScrollIntoView 和数据模板 (MVVM) 时遇到了问题,它们的变通方法相当难看。用 ScrollIntoView 恢复 ListView 状态听起来是错误的。应该有另一种方式。今天,谷歌将我引向我自己未回答的问题。

我正在寻找恢复 ListView 状态的解决方案。考虑跟随 mcve:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class ViewModel
{
    public class Item
    {
        public string Text { get; set; }
        public bool IsSelected { get; set; }

        public static implicit operator Item(string text) => new Item() { Text = text };
    }

    public ObservableCollection<Item> Items { get; } = new ObservableCollection<Item>
    {
       "Item 1",
       "Item 2",
       "Item 3 long enough to use horizontal scroll",
       "Item 4",
       "Item 5",
        new Item {Text ="Item 6", IsSelected = true }, // select something
       "Item 7",
       "Item 8",
       "Item 9",
    };
}

public partial class MainWindow : Window
{
    ViewModel _vm = new ViewModel();

    public MainWindow()
    {
        InitializeComponent();
    }

    void Button_Click(object sender, RoutedEventArgs e) => DataContext = DataContext == null ? _vm : null;
}

xaml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<StackPanel>
    <ContentControl Content="{Binding}">
        <ContentControl.Resources>
            <DataTemplate DataType="{x:Type local:ViewModel}">
                <ListView Width="100" Height="100" ItemsSource="{Binding Items}">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Text}" />
                        </DataTemplate>
                    </ListView.ItemTemplate>
                    <ListView.ItemContainerStyle>
                        <Style TargetType="ListViewItem">
                            <Setter Property="IsSelected" Value="{Binding IsSelected}" />
                        </Style>
                    </ListView.ItemContainerStyle>
                </ListView>
            </DataTemplate>
        </ContentControl.Resources>
    </ContentControl>
    <Button Content="Click"
            Click="Button_Click" />
</StackPanel>

这是一个带有 ContentControl 的窗口,其内容绑定到 DataContext(通过按钮切换为 nullViewModel 实例)。

我已经添加了 IsSelected 支持(尝试选择一些项目,隐藏/显示 ListView 将恢复)。

目的是:显示ListView,垂直和/或水平滚动(它的100x100大小,以便内容更大),单击按钮隐藏,单击按钮显示,此时 应该恢复它的状态(即 ScrollViewer 的位置)。


我认为您无法避免手动将滚动查看器滚动到上一个位置 - 无论是否使用 MVVM。
因此,您需要以一种或另一种方式存储滚动查看器的偏移量,并在加载视图时恢复它。

您可以采用实用的 MVVM 方法并将其存储在视图模型中,如下所示:WPF


n