【发布时间】:2016-05-09 20:03:45
【问题描述】:
当使用 MVVM 时,我们正在处理视图(而视图模型仍然存在)。
我的问题是如何在创建新视图时恢复ListView 状态,使其尽可能接近处置视图时的状态?
ScrollIntoView 仅部分工作。我只能滚动到单个项目,它可以在顶部或底部,无法控制项目在视图中的显示位置。
我有multi-selection(和水平滚动条,但这并不重要),有人可能会选择几个项目并且可能会进一步滚动(不改变选择)。
理想情况下,将 ScrollViewer 的 ListView 属性绑定到 viewmodel 就可以了,但我害怕直接要求这个 XY 问题(不确定 this 是否适用)。此外,在我看来,这对于 wpf 来说是一件很常见的事情,但也许我无法正确制定谷歌查询,因为我找不到相关的 ListView+ScrollViewer+MVVM 组合。
这可能吗?
我在ScrollIntoView 和数据模板 (MVVM) 方面遇到了问题,它们的变通方法相当难看。用ScrollIntoView 恢复ListView 状态听起来是错误的。应该有另一种方式。今天,谷歌将我引向我自己未回答的问题。
我正在寻找恢复ListView 状态的解决方案。考虑关注mcve:
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:
<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(通过按钮切换为null 或ViewModel 实例)。
我添加了IsSelected 支持(尝试选择一些项目,隐藏/显示ListView 将恢复)。
目的是:显示ListView,垂直和/或水平滚动(它是100x100的大小,以便内容更大),单击按钮隐藏,单击按钮显示,此时ListView应该恢复它的状态(即ScrollViewer的位置)。
【问题讨论】:
-
您可以使用
System.Windows.Interactivity。检查this方式。 -
@EgoistDeveloper,主动滚动到所选项目会产生一些副作用,并且与在接受的答案中恢复子
ScrollViewer偏移量相比不可靠。
标签: c# wpf listview mvvm scrollviewer