Динамическая генерация шаблонов (DataTemplate) для Windows Phone 7 в коде

Обычно шаблоны, описывающие внешний вид не нуждаются в динамическом изменении своего внешнего вида – они статически размещаются в ресурсах приложения и используются. Но для всякого правила бывают исключения, поэтому в данной заметке я покажу каким образом можно генерировать DataTemplate "на лету" в коде.

Представим ситуацию, в которой нам необходимо определить DataTemplate для элементов ListBox динамически в коде (для других элементов управления процедура останется той же). Чтобы это реализовать нужно выполнить следующие шаги:

  1. Сгенерировать XAML для шаблона;
  2. На основе полученного XAML получить объект DataTemplate;
  3. Задать свойство ItemTemplate для элемента ListBox.

Генерация XAML заключается в получении строки, содержащей валидный XML и соответствующей схеме XAML (http://schemas.microsoft.com/winfx/2006/xaml/presentation). В этом примере мы просто создадим строку с определением шаблона, однако в своем коде вы наверняка здесь добавите какую-то логику (иначе зачем вообще затевать динамическую генерацию шаблона?).

string source = @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
	xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
	<Grid>
		<TextBlock Text=""{Binding}"" FontSize=""40"" Background=""Red"" />
	</Grid> 
</DataTemplate>";

Для получения объекта DataTemplate на основе полученной строки следует использовать объект XamlReader. Он разбирает исходный фрагмент XAML и, если он корректен, создает на его основе объект заданного типа (таким образом, кстати, можно создавать любые объекты, а не только DataTemplate). Для разбора XAML следует выполнить метод Load() и результат привести к требуемому типу (в данном случае – DataTemplate):

DataTemplate template = (DataTemplate)XamlReader.Load(source);

Будьте осторожны, если в исходной строке содержаться ошибки (например, недопустимые символы), то вы получите ошибку времени исполнения. По-хорошему, такие ситуации следует явно отслеживать в коде и соответствующе на них реагировать.

Последнее, что необходимо сделать – присвоить полученный объект DataTemplate свойству ItemTemplate элемента ListBox. Результирующий код будет выглядеть так:

string source = @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
	xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
	<Grid>
		<TextBlock Text=""{Binding}"" FontSize=""40"" Background=""Red"" />
	</Grid> 
</DataTemplate>";

DataTemplate template = (DataTemplate)XamlReader.Load(source);

ListBox1.ItemTemplate = template;
ListBox1.ItemsSource = ...;