8

我正在使用 LongListSelector 为我的项目实现列表或网格显示。为此,我创建了一个 DataTemplateSelector 并在运行时更改了 LayoutMode 属性。这是有效的,但 DataTemplateSelector 似乎存在问题。如果我最初启动页面,DataTemplateSelector 会为我的三个项目调用三次。当我导航到另一个页面(设置页面以更改 LayoutMode)然后返回时,DataTemplateSelector 仅称为两个项目,但仍有三个项目。

数据模板选择器:

public abstract class DataTemplateSelector : ContentControl
{
    public virtual DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        return null;
    }

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        ContentTemplate = SelectTemplate(newContent, this);
    }
}

ItemViewModeTemplateSelector:

public class ItemViewModeTemplateSelector: DataTemplateSelector
{
    public DataTemplate ListViewModeTemplate
    {
        get;
        set;
    }

    public DataTemplate GridViewModeTemplate
    {
        get;
        set;
    }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        ViewMode viewMode = ViewMode.Grid;

        // Get ViewMode from IsolatedStorageSettings...

        switch (viewMode)
        {
            case ViewMode.Grid:
                return GridViewModeTemplate;

            case ViewMode.List:
                return ListViewModeTemplate;
        }

        return base.SelectTemplate(item, container);
    }
}

MainPage.xaml:

<phone:LongListSelector x:Name="ItemLongListSelector" ItemsSource="{Binding Items}" LayoutMode="Grid" GridCellSize="222,222">
    <phone:LongListSelector.ItemTemplate>
        <DataTemplate>
            <common:ItemViewModeTemplateSelector Content="{Binding}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
                <common:ItemViewModeTemplateSelector.GridViewModeTemplate>
                    <DataTemplate>
                        <StackPanel Margin="12,12,0,0" Background="{Binding Color, Converter={StaticResource ColorToBrushConverter}}">
                            <!-- Content -->
                        </StackPanel>
                    </DataTemplate>
                </common:ItemViewModeTemplateSelector.GridViewModeTemplate>

                <common:ItemViewModeTemplateSelector.ListViewModeTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <!-- Content -->
                        </StackPanel>
                    </DataTemplate>
                </common:ItemViewModeTemplateSelector.ListViewModeTemplate>
            </common:ItemViewModeTemplateSelector>
        </DataTemplate>
    </phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

这是我最初启动页面时的显示:

然后我导航到另一个页面,然后返回:

编辑:我为此问题准备了一个示例项目。它应该可以毫无问题地运行。

项目:http ://sdrv.ms/1cAbVxE

4

3 回答 3

4

我还没有找到解决方案,但也许可以为解决问题的人提供线索。
我认为问题出在 LongListSelector.UpdateLayout() 方法上——当它第一次被触发时,没有绑定 LLS 的项目——OnChangeMethod 被调用的次数与 Itemsource.Count 相同。但是当我们离开页面并返回时 - LLS 已更新并且方法称为省略中间元素。
这意味着它适用于偶数个项目 - OnChangeMethod 被正确调用次数,但对于奇数个项目 - 它被称为项目数 - 1。
第二件事是为什么它被调用 - 当没有更改时。

我还添加了一个代码来处理(非常简单)。

于 2013-11-06T12:50:14.743 回答
3

我对我的应用程序做了类似的事情,但允许用户使用 Appbar 按钮选择 LLS 的 LayoutMode。我基本上更改了 LongListSelector.LayoutMode,然后它是代码中的 ItemTemplate,LLS 会自动刷新。我不确定这是否会有所帮助,但这是我的代码。

private void layoutModeButton_Click(object sender, EventArgs e)
    {
        ApplicationBarIconButton layoutModeButton = (ApplicationBarIconButton)ApplicationBar.Buttons[0];

        if (MainLongListSelector.LayoutMode == LongListSelectorLayoutMode.Grid)
        {
            MainLongListSelector.LayoutMode = LongListSelectorLayoutMode.List;
            MainLongListSelector.ItemTemplate = this.Resources["ListListLayout"] as DataTemplate;
            layoutModeButton.IconUri = _gridButtonUri;
            layoutModeButton.Text = "grid";
        }
        else
        {
            MainLongListSelector.LayoutMode = LongListSelectorLayoutMode.Grid;
            MainLongListSelector.ItemTemplate = this.Resources["GridListLayout"] as DataTemplate;
            layoutModeButton.IconUri = _listButtonUri;
            layoutModeButton.Text = "list";
        }
    }

您可能已经想出了答案,但只是为了增加对话:这为我提供了相当大量数据的非常好的性能。在更改设置中的布局后导航回页面时,也许您可​​以做类似的事情?

于 2014-01-06T17:01:33.870 回答
1

这是一个散步。(也许问题将通过 WP 8.1 更新得到纠正,以及我发现与 LLS 一起工作的其他人。我知道 - 这个想法很丑陋,很难等等,但也许它足以满足您的目的:

因为问题关注'重新加载' LLS,我每次导航到页面时都强制它初始化它(实际上我需要初始化整个页面 - 它仅适用于 LLS)。我已经移动了 InitializeComponent() 和按钮OnNavigatedTo() 等事件:

 protected override void OnNavigatedTo(NavigationEventArgs e)
  {
     base.OnNavigatedTo(e);

     this._contentLoaded = false;
     InitializeComponent();

     first.Click += first_Click;
     second.Click += second_Click;
     ItemLongListSelector.ItemsSource = Items;
  }

至少 OnContentChanged() 被触发了它需要的多次。您可以在此处找到代码。

于 2013-11-11T17:38:17.800 回答