0

In my WP8 app, I'm using LongListSelector to display data items. Grouping works, jump list works.

I have the usual master/detail scenario here - click on item in the list, new page shows up with more information.

The problem is with navigating back to the page with LongListSelector. The list is basically messed up - items are randomly reordered, even between groups. Clicking on an item works properly - ShowItemInfo receives view model for the item the user clicked on.

Previously I was using ListBox, which too suffered from this issue. But I could disable virtualization by using default StackPanel as items panel. I don't know how to disable virtualization on LongListSelector (I don't want to, but the bug is horrible).

View model is simple. I'm using Caliburn.Micro, its conventions and BindableCollection for list of groups. I populate the list just once with AddRange method.

When the page is navigated back to, I'm not doing anything - and I even can't since I use MVVM and Caliburn.Micro. The items are loaded into list in OnInitialize callback, which is invoked only once during lifetime of view model.

The XAML for view is this:

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.Resources>
        <phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
        <phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>

        <Style x:Key="ListJumpListStyle" TargetType="phone:LongListSelector">
            <Setter Property="ItemTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <Border Background="{Binding Converter={StaticResource BackgroundConverter}}"
                                HorizontalAlignment="Stretch">
                            <TextBlock Text="{Binding GroupTitle}" 
                                       Foreground="{Binding Converter={StaticResource ForegroundConverter}}" />
                        </Border>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Grid.Resources>

    <phone:LongListSelector x:Name="Items" LayoutMode="List" IsGroupingEnabled="True"
                            JumpListStyle="{StaticResource ListJumpListStyle}">

        <phone:LongListSelector.ItemTemplate>
            <DataTemplate>
                <Grid cal:Bind.Model="{Binding}"
                      cal:Message.Attach="[Event Tap] = [ShowItemInfo($dataContext)]"
                      Background="Transparent">
                    <TextBlock x:Name="ItemText" Style="{StaticResource PhoneTextTitle2Style}" />
                </Grid>
            </DataTemplate>
        </phone:LongListSelector.ItemTemplate>

        <phone:LongListSelector.GroupHeaderTemplate>
            <DataTemplate>
                <Border>
                    <TextBlock Text="{Binding GroupTitle}" />
                </Border>
            </DataTemplate>
        </phone:LongListSelector.GroupHeaderTemplate>

    </phone:LongListSelector>
</Grid>
4

1 回答 1

0

我已将问题缩小到数据模板,更具体地说是附加属性Bind.Model,它允许 Caliburn.Micro 绑定视图模型以查看:

<DataTemplate>
    <Grid cal:Bind.Model="{Binding}"
          cal:Message.Attach="[Event Tap] = [ShowItemInfo($dataContext)]"
          Background="Transparent">
        <TextBlock x:Name="ItemText" Style="{StaticResource PhoneTextTitle2Style}" />
    </Grid>
</DataTemplate>

当此视图更改为使用显式绑定而不是约定(并Bind.Model删除附加属性)时,LongListSelector就像一个魅力。

我相信 Caliburn.Micro 中一定有一个错误,导致了这个问题。最初,我认为该错误存在于我正在使用的 1.5.2 版本中(不幸的是我必须这样做),并且它已在新的 2.x 版本中修复。然而,事实并非如此,该错误仍然出现在最新的稳定版本 2.0.2 中。

我在 WPF 中使用这种技术没有任何问题。我还尝试在 WP8.0 和 WP8.1 的模拟器中运行该应用程序,但行为是相同的。

如果有人发现导致此错误的原因(或新版本的 Caliburn.Micro 修复它),请随时编辑答案或发表评论。我很乐意再次在数据模板中使用约定。

我的错误:对于数据模板,Bind.ModelWithoutContext应该使用。甚至文档也明确表示

Bind.ModelWithoutContext - View-First - 将 Action.Target 设置为指定实例。将约定应用于视图。(在 DataTemplate 内部使用。)

使用Bind.ModelWithoutContextLongListSelector 可以正常工作(在项目模板中使用约定)。

于 2015-05-10T11:08:00.017 回答