Динамический выбор шаблона 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>

В нашем случае в выпадающем списке есть три варианта:

  • Button
  • TextBlock
  • RadioButton
    Определим для каждого варианта свой шаблон:

    <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)
            {
                int currentItem = 0;
    
                if (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}" />
    

    Запускаем приложение!

    Вот и всё…

10 Comments

  1. Огромное вам пасибо! а еще посты на эту тему будут в будущем?

  2. Ошибка:
    Имя “TemplateSelector” не существует в пространстве имен “clr-namespace:WpfApplication2”
    и
    Тип “local:TemplateSelector” не найден. Убедитесь, что не пропущена ссылка на сборку и что все сборки, на которые заданы ссылки, построены.

  3. Вы добавили в начале пространство имён?

    xmlns:local="clr-namespace:TemplateSelectorContentPresenter"
    
  4. if (element != null && item != null && item is int)
    {
    int currentItem = 0;

    int.TryParse(item.ToString(), out currentItem);

    Сначала проверяете, что item это int, а затем делаете TryParse?:)

    • На блог сейчас очень мало времени.
      Обновляется крайне редко, но материалы остаются актуальными.

Leave a Reply to VitaliyCancel Reply

Your email address will not be published. Required fields are marked *

http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_bye.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_good.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_negative.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_scratch.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_wacko.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_yahoo.gif 
http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_cool.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_heart.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_rose.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_smile.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_whistle3.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_yes.gif 
http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_cry.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_mail.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_sad.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_unsure.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_wink.gif