user3753452
user3753452

Reputation: 139

WPF DataTemplate Selector is not working

I am working on a Treeview control. The items control should display a set of textbox and combobox dynamically depending on the value of the data structure. The ArgumentTypeTemplateSelector 's convert code is executed. however, no Textbox and combo is display. Please would someone kindly help. thank you.

The tree View (xaml)

                  <ItemsControl x:Name="argumentTexts" ItemsSource="{Binding ArgumentDetailsCollection}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel HorizontalAlignment="Stretch" IsItemsHost="True" Orientation="Horizontal"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate DataType="{x:Type structures:ArgumentDetails}">
                                <ItemsControl x:Name="items" ItemsSource="{Binding DefaultValue}" 
                                              ItemTemplateSelector="{Binding DefaultValue, Converter={StaticResource ArgTypeTemplateSelector}}"/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>


public class ArgumentTypeTemplateSelector : IValueConverter
{
    private DataTemplate comboboxDataTemplate;

    private DataTemplate textboxDataTemplate;

    public DataTemplate ComboBoxDataTemplate
    {
        get
        {
            return this.comboboxDataTemplate;
        }

        set
        {
            this.comboboxDataTemplate = value;
        }
    }

    public DataTemplate TextBoxDataTemplate
    {
        get
        {
            return this.textboxDataTemplate;
        }

        set
        {
            this.textboxDataTemplate = value;
        }
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string str = (string)value;

        if (str.Contains("1"))
        {
            return this.ComboBoxDataTemplate;
        }

        return this.TextBoxDataTemplate;
    }

In the resourcedictionary(xaml)

        <DataTemplate x:Key="TextBoxDataTemplate">
            <TextBox Text="{Binding DefaultValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                                         VerticalAlignment="Center" 
                                         Width="Auto" 
                                         Margin="5,0,0,0"
                                         Padding="0" 
                                         Style="{StaticResource GridEditStyle}"
                                         IsEnabled="True"/>
        </DataTemplate>
        <DataTemplate x:Key="ComboBoxDataTemplate">
            <ComboBox HorizontalAlignment="Stretch" IsEnabled="True"/> 
        </DataTemplate>
        <columnConfiguratorControls:ArgumentTypeTemplateSelector x:Key="ArgTypeTemplateSelector" ComboBoxDataTemplate="{StaticResource ComboBoxDataTemplate}" TextBoxDataTemplate="{StaticResource TextBoxDataTemplate}"/>
    </ResourceDictionary>

Upvotes: 0

Views: 4060

Answers (1)

pgenfer
pgenfer

Reputation: 622

DataTemplateSelectors work in a different way than converters. Your DataTemplateSelector will retrieve the item of your list as argument and depending on the criteria you define, you can choose a DataTemplate that should be returned.

Try the following: In your xaml file define your DataTemplateSelector as static resource and set it in your ItemsControl:

<ItemsControl x:Name="argumentTexts" ItemsSource="{Binding ArgumentDetailsCollection}">
        <ItemsControl.Resources>
            <!-- define your template selector as static resource to reference it later -->
            <ns:ArgumentTypeTemplateSelector x:Key="ArgumentTypeTemplateSelector"/>
        </ItemsControl.Resources>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel HorizontalAlignment="Stretch" IsItemsHost="True" Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type structures:ArgumentDetails}">
                <!-- use your template selector here -->
                <ItemsControl x:Name="items" ItemsSource="{Binding DefaultValue}" 
                              ItemTemplateSelector="{StaticResource ArgumentTypeTemplateSelector }"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

In your code behind file, you need to implement your data template selector for example in the following way:

// derive from base class DataTemplateSelector
public class ArgumentTypeTemplateSelector : DataTemplateSelector
{
    // override SelectTemplate method
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        // get access to the resources you need, for example
        // by accessing the UI object where your selector is placed in
        var frameworkElement = (FrameworkElement) container;

        // return a data template depending on your custom logic,
        // you can cast "item" here to the specific type and check your conditions
        if(item has condition)
        return (DataTemplate) frameworkElement.FindResource("YourDataTemplateKey");
        else
            // ...
        return base.SelectTemplate(item, container);
    }
}

Upvotes: 2

Related Questions