В этой статье я расскажу что такое DataTemplateSelector, как создавать абстрактные и пользовательские классы DataTemplateSelector в Windows Phone 8. Что же такое DataTemplateSelector? — это класс который обеспечивает выбор DataTemplate, основанного на объекте данных и элементе, связанным с данными (msdn). Иными словами, если у вас есть допустим ListBox, и вы хотите в нем отображать, одновременно, более чем один DataTemplate (стиль отображения) для разных данных, тогда вам нужно использовать DataTemplateSelector с помощью которого вы сможете создать собственную логики для выбора DataTemplate.Для лучшей ясности рассмотрим как реализовать абстрактный класс DataTemplateSelector.Сейчас создадим абстрактный класс (для тех кто не знает какой класс называется абстрактным читать msdn) который является производным от ContentControl в нем с помощью виртуального метода SelectTemplate будет обеспечиваться логика для возврата соответствующего шаблона, и перегрузим OnContentChanhed который исходит от базового класса.
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);
}
}
Далее нужно создать так званный «кастомный» DataTemplateSelector который будет наследоваться от DataTemplateSelector, это для того чтоб была возможность выбора DataTemplate. Здесь все просто.
public class MyTemplateSelector : DataTemplateSelector
{
public DataTemplate Maximum { get; set; }
public DataTemplate Middle { get; set; }
public DataTemplate Minimum { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var myItem = item as Data;
if (myItem != null)
{
switch (myItem.Type)
{
case "Maximum":
return Maximum;
case "Middle":
return Middle;
case "Minimum":
return Minimum;
}
}
return base.SelectTemplate(item, container);
}
}
А сейчас немножко пройдемся по нашему «кастомном» DataTemplateSelector. Это обычный класс который наследуется от DataTemplateSelector, в нем определено три свойства Maximum, Middle, Mimimum которые являются DataTemplate для выбора шаблонов. Далее идет перезагрузка метода SelectTemplate в котором через оператор switch определяется условия выбора соответствующего DataTemplate.После этого напишем простой класс данных который будет иметь свойства для привязки данных к нашему ListBox и сделаем несколько конструкторов, для разных DataTemplate свой отдельно:
public class Data
{
public string Name { get; set; }
public string Description { get; set; }
public string Images { get; set; }
public string Type { get; set; }
#region Constructor
public Data(string description, string name, string images, string type)
{
Description = description;
Name = name;
Images = images;
Type = type;
}
public Data(string description, string name, string type)
{
Description = description;
Name = name;
Type = type;
}
public Data(string description, string type)
{
Description = description;
Type = type;
}
#endregion
}
Все самое сложное мы сделали, все что нам остается это создать ListBox с тремя разными шаблонами (Maximum, Middle, Minimum) и привязкою к нашему «кастомном» DataTemplateSelector, и конечно наполнить наш ListBox.XAML ListBox:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<local:MyTemplateSelector>
<local:MyTemplateSelector.Maximum>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Margin="8" Source="{Binding Images}"
VerticalAlignment="Center" Width="48" Height="48"/>
<StackPanel>
<TextBlock Margin="8" Text="{Binding Name}" Width="250"
VerticalAlignment="Top" HorizontalAlignment="Left"/>
<TextBlock Width="100" Text="{Binding Description}" Margin="8,0,8,8"
VerticalAlignment="Top" HorizontalAlignment="Left"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</local:MyTemplateSelector.Maximum>
<local:MyTemplateSelector.Middle>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="8" Text="{Binding Name}" Width="250"
VerticalAlignment="Top" HorizontalAlignment="Left" />
<TextBlock Width="250" Text="{Binding Description}" Margin="8,0,8,8"
VerticalAlignment="Top" HorizontalAlignment="Left"/>
</StackPanel>
</DataTemplate>
</local:MyTemplateSelector.Middle>
<local:MyTemplateSelector.Minimum>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="8" Text="{Binding Description}" Width="250"
VerticalAlignment="Top" HorizontalAlignment="Left" />
</StackPanel>
</DataTemplate>
</local:MyTemplateSelector.Minimum>
</local:MyTemplateSelector>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
И наконец заполнения данными, можно после инициализации дописать или перезагрузить метод OnNavigatedTo, или еще как то придумать, это не столь важно:
var list = new List<Data>();
var itemData0 = new Data("Notebook", "Dell", "Assets/BrandIcon/dellIcon.jpg", "Maximum");
var itemData1 = new Data("Mouse", "Zalman", "Middle");
var itemData2 = new Data("Ultrabook", "LG", "Assets/BrandIcon/lgIcon.jpg", "Maximum");
var itemData3 = new Data("Other", "Minimum");
list.Add(itemData0);
list.Add(itemData1);
list.Add(itemData2);
list.Add(itemData3);
MyListBox.ItemsSource = list;
Вот и все, можно компилировать и смотреть как в нашем ListBox отображаются сразу три разных DataTemplate. Чтоб лучше разобраться как все работает соберите проект сами, если не будет получаться то вот исходник GitHub.Пишите, пробуйте, ели что задавайте вопросы, буду рад помочь :)
Автор: Taras_Kovalenko