When using MVVM we are disposing view (while viewmodel persists).
My question is how to restore ListView
state when creating new view as close as possible to one when view was disposed?
ScrollIntoView works only partially. I can only scroll to a single item and it can be on top or bottom, there is no control of where item will appears in the view.
I have multi-selection (and horizontal scroll-bar, but this is rather unimportant) and someone may select several items and perhaps scroll further (without changing selection).
Ideally binding ScrollViewer
of ListView
properties to viewmodel would do, but I am afraid to fall under XY problem asking for that directly (not sure if this is even applicable). Moreover this seems to me to be a very common thing for wpf, but perhaps I fail to formulate google query properly as I can't find related ListView
+ScrollViewer
+MVVM
combo.
Is this possible?
I have problems with ScrollIntoView
and data-templates (MVVM) with rather ugly workarounds. Restoring ListView
state with ScrollIntoView
sounds wrong. There should be another way. Today google leads me to my own unanswered question.
I am looking for a solution to restore ListView
state. Consider following as 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>
This is a window with ContentControl
which content is bound to DataContext
(toggled by button to be either null
or ViewModel
instance).
I've added IsSelected
support (try to select some items, hiding/showing ListView
will restore that).
The aim is: show ListView
, scroll (it's 100x100
size, so that content is bigger) vertically and/or horizontally, click button to hide, click button to show and at this time ListView
should restore its state (namely position of ScrollViewer
).