Динамическое отображение элементов с использованием FlipView и DataTemplateSelector в WinRT
Я использую 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);
}
}
Я думаю, что это может быть достигнуто с помощью групп и просмотра списка. Но я не уверен, как это можно сделать.
Возможно, это глупый вопрос, но, используя Google, я не могу найти ответ. Также английский не является моим родным языком; пожалуйста, извините ошибки ввода.
Ответы
Ответ 1
Я думаю, что способ добиться того, что вы ищете, - это разоблачить данные таким образом, чтобы лучше представлять то, что вы хотите отобразить. Затем вы можете использовать вложенные элементы управления для его отображения. Я просто выбросил это вместе (используя свои собственные тестовые данные). Это, вероятно, не совсем то, что вы хотите, но это должно помочь вам разобраться.
ViewModel
Здесь я сделал вспомогательный метод для создания коллекции с подкатегориями, каждая из которых имеет 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<T>
и Object
, я не знаю, как распознать разницу, используя только DataTemplate.TargetType
свойство из Xaml, поскольку List<T>
является общим типом. (Я пробовал {x:Type collections:List`1}
, и он не работал.)
Ответ 2
Вам нужно сгруппировать элементы в viewmodel и databind 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());
и вам нужно использовать другой Datatemplaeselector или нечетные datatemplates в FlipView, чтобы различать FirstPage и PageGroup
<FlipView ItemsSource="{Binding Pages}"
ItemTemplateSelector="{StaticResource PageTemplateSelector}" />
Ответ 3
Вам не нужно беспокоиться о выборе соответствующего шаблона на основе типа класса, вы можете просто определить класс в самом DataTemplate
.
<DataTemplate TargetType="{x:Type myNamespace:FirstItem}">
...
</DataTemplate>
Вам нужно указать, где находится класс, добавив пространство имен в верхней части страницы:
xmlns:myNamespace="clr-namespace:MyApp.MyNamespace"