【问题标题】:LongListSelector and DataTemplateSelectorLongListSelector 和 DataTemplateSelector
【发布时间】:2014-01-07 01:01:33
【问题描述】:

我正在使用 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

【问题讨论】:

  • 我添加了一个示例项目!
  • 你找到问题了吗?
  • 不,问题仍然存在!
  • 确实是个很好奇的问题,我知道这听起来有点蹩脚,但是,如果你使用 ListBox 并绑定 ItemTemplate?
  • 我已经在使用 ListBox,但我想切换到 LongListSelector,因为它不能很好地与 ContextMenu 一起使用。你可以在这里看到我的 ListBox 问题:stackoverflow.com/questions/19609850/…

标签: c# windows-phone-8 windows-phone longlistselector datatemplateselector


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    我对我的应用做了类似的事情,但允许用户使用 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";
            }
        }
    

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

    【讨论】:

    • 这也有效!我认为这似乎是对性能更友好的方式。谢谢。
    【解决方案3】:

    这是一个走一走。 (也许问题将通过 WP 8.1 更新以及others 得到纠正,我发现使用 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() 被触发了很多次。代码你可以找到here

    【讨论】:

    • 这行得通,但我不确定它会如何影响我的许多项目的表现。我将对其进行测试,如果它太糟糕,我将删除更改布局模式的选项。谢谢,这对我很有帮助! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多