Reputation: 27595
PersonsViewModel
has a corresponding DataTemplate with a DataGrid bound to PersonList
. DataGrid.SelectedItem
has two-way databinding to SelectedPerson
, so that when I select a row in the view, the corresponding item from PersonList
is assigned to SelectedPerson
.
It works fine except for one problem: when I switch screens, say, to PersonDetailScreen
, and come back, the selection focus is lost! I mean, SelectedPerson
still contains its former value, but the DataGrid comes out visually unselected.
I made a test, creating a two-way databound "SelectedIndex" in viewmodel. Then, I can see the actual selection is still present in viewmodel when it comes back, the problem seems to be:
"How to focus the SelectedIndex
of an ItemsControl
when ViewModel's datatemplate is loaded and some "SelectedIndex" databound property in such viewmodel already contains a value?"
Upvotes: 0
Views: 932
Reputation: 27595
Thanks to Sheridan's insights, I have solved the problem easier than I imagined, and somewhat unintentionally.
I had the DataGrid defined directly in a DataTemplate. When the template loaded, I BELIEVE, although I am not sure at all, that some initialization step required to pass the "SelectedItem" or "SelectedItem" value to the View was "lost".
I planned to do this re-selection manually in code behind, so what I did was to move the datagrid to some UserControl I created from scratch. But then, the very fact that the DataTemplate now instantiates a proper View (derived from UserControl) inside itself, which in turn contains the datagrid, seems to "make more notifications work", so to say, and the View displays selected row like it always should.
So, now I have this in my DataTemplate:
<DataTemplate x:Name="PersonScreenTemplate" DataType="{x:Type vm:PersonScreenViewModel}">
<vw:PersonScreenViewView/>
</DataTemplate>
That seems to be the perfect pure-WPF design pattern for ViewModel-first: a datatemplate whose content is a single usercontrol, which in turn declares and binds and handles everything.
Upvotes: 0
Reputation: 43
What are we talking about here, item selection or item focus?
If you want a visual item to get focus when a template is rendered, your best bet is to set the focus manually in your xaml's code behind, by, say, hooking a handler to your page's 'Loaded' event and setting the focus manually to your datagrid by calling on its 'Focus()' method.
I know this breaks some MVVM rules, but focus management is highly dependent on your page's visual tree, and thus cannot be properly modeled through a viewmodel, which should be as view-independent as possible.
Upvotes: 0
Reputation: 69979
If you have a TwoWay Binding
then you can set the DataGrid.SelectedItem
value from your view model. I'm a little bit confused as to your set up though... when you say 'when I switch screens ... and come back, the selection focus is lost', it sounds a bit like you're keeping the view model alive, but not the view? I'm more used to displaying a fresh view each time, but the fix would be the same either way.
Now if this were one of my views, I'd load the data into any collections from the constructor and (internally in a base class) set the CurrentItem
property that is data bound to the ListBox.SelectedItem
property to the first item in the collection. You should do the same, except that instead of setting it to the first item, you'd set it to whichever item was last selected.
So the answer is just to set the SelectedItem
property each time the view is displayed. However, if you're saying that the SelectedItem
property is already set to the item that should be selected, you may need to set it to any other value first and then set it back to the correct item.
Upvotes: 1