Динамический выбор шаблона DataTemplateSelector
Бывает ситуация, когда заранее не знаеш, какой шаблон необходимо подключить. Для этого WPF предусматривает DataTemplateSelector. Давайте на примере посмротрим, как всё это работает.
Создадим простое WPF приложение. Разместим на форме ComboBox и ContentPresenter:
<Window x:Class="TemplateSelectorContentPresenter.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="240" Width="344"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <ComboBox Grid.Row="0" SelectionChanged="OnChange" Margin="5"> <ComboBoxItem>Button</ComboBoxItem> <ComboBoxItem>TextBlock</ComboBoxItem> <ComboBoxItem>RadioButtons</ComboBoxItem> </ComboBox> <ContentPresenter x:Name="presenter" Grid.Row="1" Margin="5" /> </Grid> </Window>
В нашем случае в выпадающем списке есть три варианта:
Определим для каждого варианта свой шаблон:
<Window.Resources> <DataTemplate x:Key="ButtonTemplate"> <Button Content="Click Me" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Center" /> </DataTemplate> <DataTemplate x:Key="TextBlockTemplate"> <TextBlock Text="TextBlock" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Center" /> </DataTemplate> <DataTemplate x:Key="RadioButtonsTemplate" > <Grid Margin="5" VerticalAlignment="Center" HorizontalAlignment="Center" > <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <RadioButton Content="Variant 1" Grid.Row="0" /> <RadioButton Content="Variant 2" Grid.Row="1" /> <RadioButton Content="Variant 3" Grid.Row="2" /> </Grid> </DataTemplate> </Window.Resources>
Для ComboBox подпишемся на событие SelectionChanged. В обработчике мы будем присваивать свойтсву Content ContentPresenter-а выбраный индекс:
private void OnChange(object sender, SelectionChangedEventArgs e) { ComboBox cb = sender as ComboBox; if (cb != null && presenter != null) presenter.Content = cb.SelectedIndex; }
Теперь определим наш DataTemplateSelector:
public class TemplateSelector : DataTemplateSelector { public override DataTemplate SelectTemplate(object item, DependencyObject container) { //получаем вызывающий контейнер FrameworkElement element = container as FrameworkElement; if (element != null && item != null && item is int) { int currentItem = 0; int.TryParse(item.ToString(), out currentItem); //в зависимости от того, какой вариант выбран, возвращаем конкретный шаблон if (currentItem == 0) return element.FindResource("ButtonTemplate") as DataTemplate; if (currentItem == 1) return element.FindResource("TextBlockTemplate") as DataTemplate; if (currentItem == 2) return element.FindResource("RadioButtonsTemplate") as DataTemplate; } return null; } }
Подключаем простарнство имён:
xmlns:local="clr-namespace:TemplateSelectorContentPresenter"
Определяем ресурс:
<local:TemplateSelector x:Key="templateSelector" />
Подключаем наш TemaplteSelector к ContentPresenter
Определяем ресурс:
<ContentPresenter x:Name="presenter" Grid.Row="1" Margin="5" ContentTemplateSelector="{StaticResource templateSelector}" />
Запускаем приложение!
Вот и всё…
TemplateSelectorContentPresenter.rar (89,1 KiB, 1 867 закачек)
Огромное вам пасибо! а еще посты на эту тему будут в будущем?
Будут обязательно
Ошибка:
Имя «TemplateSelector» не существует в пространстве имен «clr-namespace:WpfApplication2″
и
Тип «local:TemplateSelector» не найден. Убедитесь, что не пропущена ссылка на сборку и что все сборки, на которые заданы ссылки, построены.
Когда добавляю local:TemplateSelector x:Key=»templateSelector»
Вы добавили в начале пространство имён?
Все кратко и понятно. Огромное спасибо!
if (element != null && item != null && item is int)
{
int currentItem = 0;
int.TryParse(item.ToString(), out currentItem);
…
Сначала проверяете, что item это int, а затем делаете TryParse?:)
Так надёжней…
Только не очень могу понять как часто обновляется ваш блог
На блог сейчас очень мало времени.
Обновляется крайне редко, но материалы остаются актуальными.