The porblem is ItemsPanel:
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
if I remove this from Combo, it works with ItemsPresenter BUT if I keep it, I've to replace ItemsPresenter with someother ItemsHost! I'm not sure whether these:
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="VirtualizingPanel.IsVirtualizing" Value="True"/>
<Setter Property="VirtualizingPanel.VirtualizationMode" Value="Recycling"/>
in Setter instead of ItemsPanel enables UI Virtualization or not.
EDIT
It also works with ItemsPanel and without those three top level Setter, if I Refresh
the view on Add
static void onCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
var view = sender as ICollectionView;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
if (view.CurrentItem != e.NewItems[0])
{
view.MoveCurrentTo(e.NewItems[0]);
//view.Refresh();
}
break;
case NotifyCollectionChangedAction.Reset:
if (e.NewItems == null && !view.IsEmpty)
view.MoveCurrentToFirst();
break;
}
}
BUT why would I do that? What's the point of IsSynchronizedWithCurrentItem=true
?
I've two static ICollectionView
(Plots and ControlHeads) which don't have filter/sort/grouping and are bound to several ComboField in different views. To reduce the hit in CurrentChanged
handlers in different viewmodels I've added this:
if (view.CurrentItem != e.NewItems[0])
view.MoveCurrentTo(e.NewItems[0]);
and as the CurrentItem is in one place, static ICollectionView, and I've IsSynchronizedWithCurrentItem=true
, I neither have to move everywhere nor refresh the view right?
EDIT
Visually the Combo in the ComboField is in sync with CurrentItem and the SelectedItem
is also in sync. With this in the overridden OnItemsChanged
of Combo
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
if(SelectedItem != e.NewItems[0])
SelectedItem = e.NewItems[0];
break;
case NotifyCollectionChangedAction.Reset:
if (e.NewItems == null && !Items.IsEmpty)
Items.MoveCurrentToFirst();
break;
}
}
I can see that in case of ICollectionView, Plots
, it hits Add 6 times (there're 6 ComboField bound to static ICollectionView Plots) when I add a plot and it escapes the assignment of SelectedItem
5 times. The one that assigns the SelectedItem = e.NewItems[0]
, shows the popup when I click on toggle BUT the rest which escaped the assignment, throws the exception!
To get rid of this exception I've to reassign SelectedItem = e.NewItems[0]
for all by removing the if
guard in Add block and ComboField's onCollectionChanged
can be empty.
So the question is why do I have to reassign?
EDIT
Moving the code in Combo instead of ComboField doesn't solve the problem either, for some reason it worked once/twice when I wrote! After deleting bin, obj, .vs folders, now the first Combo in Space section of UI works BUT the second in the Lease section throws that:
so as I move the code from ComboField.cs to Combo.cs, the exception moves.