【问题标题】:Dynamically displaying Items using FlipView and DataTemplateSelector in WinRT在 WinRT 中使用 FlipView 和 DataTemplateSelector 动态显示项目
【发布时间】:2015-05-22 13:22:50
【问题描述】:

我正在使用 Flipview 和 DataTemplateSelector 来确定在运行时应用哪个 DataTemplate 来显示我的控件中的项目。

我有两个 DataTemplate,一个是静态的,第二个可以用于不确定数量的项目。

目前

我的第一个视图显示: - “这是一个测试 - 内容”

Followed by 18 other views 看起来像这样: -“http://www.google.com/0” -“http://www.google.com/1” -“http://www.google.com/2” - 以此类推,直到 17 点

我想要

项目“http://www.google.com/”被分组为3 on a view

例如第二个视图会显示:

将显示第三个视图:

等等..

下面是我的代码:

FlipViewDemo.xaml

<Page.Resources>
    <DataTemplate x:Key="FirstDataTemplate">
        <Grid>
            <TextBlock Text="{Binding Content}" Margin="10,0,18,18"></TextBlock>
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="SecondDataTemplate">
        <TextBox Text="{Binding Url}"></TextBox>
    </DataTemplate>
    <local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
                FirstTextTemplate="{StaticResource FirstDataTemplate}"
                SecondTextTemplate="{StaticResource SecondDataTemplate}">
    </local:MyDataTemplateSelector>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <FlipView x:Name="itemGridView" ItemTemplateSelector="{StaticResource MyDataTemplateSelector}" 
    Margin="265,220,284,162">
    </FlipView>
</Grid>

FlipViewDemo.xaml.cs

public sealed partial class FlipViewDemo : Page
{
    public FlipViewDemo()
    {
        this.InitializeComponent();

        var items = new List<BaseClass>();

        items.Add(new FirstItem
        {
            Content="This is a test - Content"
        });

        for (int i = 0; i < 18; i++)
        {
            items.Add(new SecondItem
            {
                Url = "http://www.google.com/ " + i.ToString() 
            });
        }
        itemGridView.ItemsSource = items;
    }
}
public class BaseClass
{
}

public class FirstItem : BaseClass
{
    public string Content { get; set; }
}

public class SecondItem : BaseClass
{
    public string Url { get; set; }
}

public class MyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate FirstTextTemplate { get; set; }
    public DataTemplate SecondTextTemplate { get; set; }

    protected override DataTemplate SelectTemplateCore(object item,
                                                       DependencyObject container)
    {
        if (item is FirstItem)
            return FirstTextTemplate;
        if (item is SecondItem)
            return SecondTextTemplate;

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

我想也许这可以通过组和列表视图来实现。但我不确定如何做到这一点。

这可能是一个愚蠢的问题,但使用谷歌,我找不到答案。英语也不是我的母语;请原谅打字错误。

【问题讨论】:

    标签: c# .net wpf xaml windows-runtime


    【解决方案1】:

    我认为实现您正在寻找的方法是以更好地代表您想要显示的内容的方式公开数据。然后,您可以使用嵌套控件来显示它。我只是把它放在一起(使用我自己的测试数据)。这可能不是您想要的,但它应该可以帮助您解决问题。

    视图模型
    在这里,我创建了一个辅助方法来构建包含子集合的集合,每个子集合都有 3 个项目。

    class FlipViewDemo
    {
        private List<object> mData;
    
        public IEnumerable<object> Data
        {
            get { return mData; }
        }
    
        public FlipViewDemo()
        {
            mData = new List<object>();
            mData.Add("Test String");
            for (int i = 0; i < 18; ++i)
            {
                AddData("Test Data " + i.ToString());
            }
        }
    
        private void AddData(object data)
        {
            List<object> current = mData.LastOrDefault() as List<object>;
            if (current == null || current.Count == 3)
            {
                current = new List<object>();
                mData.Add(current);
            }
            current.Add(data);
        }
    }
    
    class TemplateSelector : DataTemplateSelector
    {
        public DataTemplate ListTemplate { get; set; }
        public DataTemplate ObjectTemplate { get; set; }
    
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item is List<object>) return ListTemplate;
            return ObjectTemplate;
        }
    }
    

    Xaml
    这里我使用 ItemsControl 来垂直堆叠数据中的项目。每个项目要么是三个对象的列表,要么是一个对象。我对三个对象的列表中的每一个都使用FlipView,对单个对象使用简单的ContentPresenter

    <Page.Resources>
        <DataTemplate x:Key="ListTemplate">
            <FlipView
                ItemsSource="{Binding}">
                <FlipView.ItemTemplate>
                    <DataTemplate>
                        <ContentPresenter
                            Margin="0 0 10 0"
                            Content="{Binding}" />
                    </DataTemplate>
                </FlipView.ItemTemplate>
            </FlipView>
        </DataTemplate>
        <DataTemplate x:Key="ObjectTemplate">
            <ContentPresenter
                Margin="0 0 10 0"
                Content="{Binding}" />
        </DataTemplate>
        <local:TemplateSelector
            x:Key="TemplateSelector"
            ListTemplate="{StaticResource ListTemplate}"
            ObjectTemplate="{StaticResource ObjectTemplate}" />
    </Page.Resources>
    
    <ItemsControl
        ItemsSource="{Binding Data}"
        ItemTemplateSelector="{StaticResource TemplateSelector}" />
    

    注意:您通常不需要这样的模板选择器,但由于您需要在 List&lt;T&gt;Object 之间进行选择,我不知道仅使用 @ 来识别差异来自 Xaml 的 987654327@ 属性,因为 List&lt;t&gt; 是泛型类型。 (我试过{x:Type collections:List`1},但没用。)

    【讨论】:

    • 嗨,泽维尔,非常感谢。我试图在模拟器中运行它,但没有得到任何东西,只是黑屏。这对你有用吗?
    • 它确实对我有用,但我的设置与您的原始设置略有不同。我将 FlipViewDemo 做成了一个单独的类,并将其设置为视图上的数据上下文,而不是将代码放在代码隐藏中。此外,我将它作为常规的 Windows WPF 应用程序而不是 WinRT 运行(因为我没有为此设置)。我只打算将代码作为参考,而不是直接运行示例。我主要想强调解决您的具体问题的领域。
    【解决方案2】:

    您需要在 viewmodel 中对项目进行分组,并将 ItemsSource 数据绑定到这些组。在 Flipview 的 itemtemplate 中,您可以分组显示项目。

    public class PageGroup : PageBase {
        public ObservableColection<BaseClass> Items { get; set; }
    }
    
    public ObservableCollection<PageBase> Pages { get; set; }
    
    <FlipView ItemsSource="{Binding Pages}">
         <FlipView.ItemTemplate>
             <DataTemplate DataType="local:PageGroup">
                 <ItemsControl ItemsSource="{Binding Items}"
                               ItemTemplateSelector="{StaticResource MyDataTemplateSelector}" />
             </DataTemplate>
         </FlipView.ItemTemplate>
     </FlipView>
    

    为了以不同于其他页面的方式显示第一页:

    public class FirstPage : PageBase {
        public string Title { get; }
    }
    
    Pages.Insert(0, new FirstPage());
    

    你需要在 FlipView 中使用另一个 datatemplaeselector 或 impicit datatemplates 来区分 FirstPage 和 PageGroup

    <FlipView ItemsSource="{Binding Pages}" 
              ItemTemplateSelector="{StaticResource PageTemplateSelector}" />
    

    【讨论】:

      【解决方案3】:

      您无需担心根据类类型选择合适的模板,只需在DataTemplate 本身中定义类即可。

      <DataTemplate TargetType="{x:Type myNamespace:FirstItem}">
         ...
      </DataTemplate>
      

      您需要通过在页面顶部添加命名空间来指定类的位置:

      xmlns:myNamespace="clr-namespace:MyApp.MyNamespace"
      

      【讨论】:

      • 嗨,迈克,感谢您的回答。我不明白这如何帮助我在每个视图中显示 3 个项目而不是 1 个
      • 我相信他只是说您可以删除模板选择器并更新数据模板本身以在其上定义TargetType。这将简化您现有的代码,但它不能回答您的实际问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多