ObservableCollection 的行为在 UWP 和 WASM 上不同

Behavior of ObservableCollection is different on UWP and WASM

我有一个 uno 应用程序,其中 observableCollection 在 UWP 和 WASM 平台上的行为不同。

它出现在 GridView 中,其中 ItemsWrapGrid 指定为 itemsPanel。 ItemSource 是一个 ObservableCollection。这是 xaml:

<GridView x:Name="gView" ItemsSource="{Binding Pictures,Mode=OneWay}" SelectionMode="Extended" IsMultiSelectCheckBoxEnabled="False" 
          VerticalAlignment="Stretch" HorizontalAlignment="Center" SelectionChanged="ImageSelectionChanged" >
    <GridView.ItemContainerStyle>
        <Style TargetType="GridViewItem">
            <Setter Property="Margin" Value="10"/>
        </Style>
    </GridView.ItemContainerStyle>
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <not_wasm:ItemsWrapGrid Orientation="Horizontal"  MaximumRowsOrColumns="8"/>
            <wasm:WrapPanel/>
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
    <GridView.ItemTemplate>
        <DataTemplate>
            <Grid Margin="4">
                <Image Source="{Binding URL}" Width="{Binding Parent.ImageWidth, Mode=TwoWay}" MinWidth="200"/>
                <TextBlock Text="{Binding PictureKey}" Foreground="Yellow" FontSize="14" HorizontalAlignment="Center"
                           VerticalAlignment="Bottom" Margin="0,0,10,0"/>
            </Grid>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

用户可以 select 项并将其从视图中删除。这是相关代码:

if (result == 1)
{
    int ndx = vm.EvtViewModel.Pictures.IndexOf(pict);
    vm.EvtViewModel.Pictures.Remove(pict);
    if (ndx < vm.EvtViewModel.Pictures.Count)
    {
        vm.EvtViewModel.SelectedPicture = vm.EvtViewModel.Pictures[ndx];
    }
    else
    {
        vm.EvtViewModel.SelectedPicture = vm.EvtViewModel.Pictures.Count > 0 ? vm.EvtViewModel.Pictures.Last() : null;
    }
}

其中 vm.EvtViewModel.Pictures 是 ObservableCollection。问题是在 UWP 上,项目被删除,它们下面的剩余项目被移到列表中。在 WASM 上,它会触发网格的完全重绘。

有办法解决这个问题吗?

这个问题没有简单的解决办法,但会在即将发布的 Uno 版本中部分解决。要了解该问题,请注意您在 WebAssembly 上使用 WrapPanel,在 UWP 上使用 ItemsWrapGrid,这是推荐的方法,因为 ItemsWrapGrid isn't yet implemented for WASM.

WrapPanel 是一个 'non-virtualizing' 面板,这意味着它急切地为项目源中的所有项目创建视图。目前,非虚拟化面板未针对在 WASM 上与 ObservableCollection 一起使用进行优化。 this change 将解决此问题,这将防止在插入单个项目时重新绘制整个网格。