Caliburn.Micro
Caliburn.Micro copied to clipboard
[UWP] ListViewItem lost context after manipulations with IGrouping
Hey. I've got an issue when trying to use SemanticZoom with CollectionViewSource. When trying to delete group and insert/add it back after update - some/all of items lost context and attached actions don't fire.
DataTemplates
<DataTemplate x:Key="MovementGroupByDateDataTemplate">
<Grid d:DataContext="{d:DesignInstance movementsItemViewModels:MovementsGroupedByTimeItemViewModel}"
micro:Action.TargetWithoutContext="{Binding ElementName=Root, Path=DataContext}">
<Grid Margin="12,21,12,9">
</Grid>
</Grid>
</DataTemplate>
<DataTemplate x:Key="MovementDataTemplate">
<controls:SlidableListItem d:DataContext="{d:DesignInstance movementsItemViewModels:MovementItemViewModel}"
x:Name="GridItem"
RightIcon="Delete" RightBackground="{StaticResource DeleteBrush}"
RightLabel="Delete"
LeftIcon="Edit" LeftBackground="{StaticResource AccountBrush}"
LeftLabel="Edit"
ActivationWidth="150" MouseSlidingEnabled="True"
micro:Message.Attach="[Event LeftCommandRequested] = [Action Edit()];
[Event RightCommandRequested] = [Action Delete()]"
IsLeftCommandEnabled="{Binding IsSelected}"
IsEnabled="{Binding IsSelected}"
IsRightCommandEnabled="{Binding IsSelected}">
<Grid>
</Grid>
</controls:SlidableListItem>
</DataTemplate>
Page
<Page.Resources>
<CollectionViewSource x:Name="AllMovementsCollection" x:Key="AllMovementsCollection"
Source="{Binding Path=All.Items, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsSourceGrouped="True"/>
</Page.Resources>
<Grid x:Name="Root">
<SemanticZoom>
<SemanticZoom.ZoomedOutView>
<ListView ItemsSource="{Binding Path=CollectionGroups, Source={StaticResource AllMovementsCollection}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
MaxWidth="{StaticResource MaxWidth}"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
ItemContainerStyle="{StaticResource WalletListViewItemWithoutMargin}"
ItemTemplate="{StaticResource ZoomOutMovementGroupByDateDataTemplate}"
SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Hidden"/>
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<ListView ItemsSource="{Binding Source={StaticResource AllMovementsCollection}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
SelectedItem="{Binding All.SelectedMovement, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
MaxWidth="{StaticResource MaxWidth}"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
ItemContainerStyle="{StaticResource WalletListViewItemWithoutMargin}"
ItemTemplate="{StaticResource MovementDataTemplate}"
SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Hidden"
ShowsScrollingPlaceholders="True">
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="True" HeaderTemplate="{StaticResource MovementGroupByDateDataTemplate}"/>
</ListView.GroupStyle>
</ListView>
</SemanticZoom.ZoomedInView>
</SemanticZoom>
</Grid>
Code
var movementsGroup = MainContentViewModel.All.Items.First(gi => gi.Items.Any(i => i.Movement.Id == _deleteMovement.Movement.Id));
int groupIndex = MainContentViewModel.All.Items.IndexOf(movementsGroup);
var groupMovements = new List<MovementItemViewModel>(movementsGroup.Items);
groupMovements.Remove(groupMovements.First(m => m.Movement.Id == _deleteMovement.Movement.Id));
MainContentViewModel.All.SelectedMovement = null;
MainContentViewModel.All.Items[groupIndex] = _viewModelFactoryService.ResolveViewModel<MovementsGroupedByTimeItemViewModel, IEnumerable<MovementItemViewModel>>(groupMovements); // IoC.Get
// or
var movementsGroup = MainContentViewModel.Expenses.Items.First(gi => gi.Items.Any(i => i.Movement.Id == _deleteMovement.Movement.Id));
int groupIndex = MainContentViewModel.Expenses.Items.IndexOf(movementsGroup);
MainContentViewModel.Expenses.Items.RemoveAt(groupIndex);
movementsGroup.Items.Remove(_deleteMovement);
if (movementsGroup.Items.Any())
{
await movementsGroup.RecalculateAmounts();
if (groupIndex > MainContentViewModel.All.Items.Count)
{
MainContentViewModel.Expenses.Items.Add(movementsGroup);
}
else
{
MainContentViewModel.Expenses.Items.Insert(groupIndex, movementsGroup);
}
}
Delete implemented this way, because if try to remove nested element itself - ListView doesn't update.
I'm not sure off the top of head what's going wrong here, if you can provide a small sample that illustrates the problem I'll dig into it in more detail.
https://github.com/dmitriywind/CaliburnIssueExample
Try to delete items inside 1 group (in diff orders).