简体   繁体   中英

WPF TemplateSelector in custom control - usage in code

In my MVVM project, I had to create a custom control RowGrid inheriting from grid. This control has an ItemsSource and an ItemsTemplateSelector . (I am not using an ItemsControl, because I need to set aa relative size for each child, and I am doing it by setting the column-widths to x*) I am trying to assign the template with the ItemsTemplateSelector in code, but it does not work properly:

Children.Clear();
int i = 0;
foreach (var element in ItemsSource)
{
    if (element != null)
    {
        DataTemplate dataTemplate = ItemTemplateSelector.SelectTemplate(element, null);
        ContentControl contentControl = new ContentControl
        {
            DataContext = element, 
            ContentTemplate = dataTemplate
        };
        Children.Add(contentControl);
        SetColumn(contentControl, i);
    }
    i++;
}

the ItemTemplateSelector.SelectTemplate is a simple switch/case where, depending on the type of element, a specific DataTemplate is returned.

A DataTemplate example is the following:

<DataTemplate x:Key="StringTemplate">
    <Grid>
       <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Label Content="{Binding Name}" Grid.Column="0"></Label>
        <customControls:MyStringTextBox MyString="{Binding}" Grid.Column="1"/>
    </Grid>
</DataTemplate>

If instead of my RowGrid custom control, I use a ItemsControl, the bindings of the DataTemplate work.

If I use my custom control, they do not.

This means that the ItemsSource is fine, the ItemsTemplateSelector is fine and the DataTemplate is fine. The issue is how I am putting together DataTemplate and its ViewModel

What am I doing wrong? What am I missing?

Thank you for any support!

I do not really like it, but I found a solution:

I initialize the contentControl this way:

ContentControl contentControl = MergeTemplateWithContext(dataTemplate, element)

plus

public static ContentControl MergeTemplateWithContext(DataTemplate template, object context)
{
    ContentControl contentControl = new ContentControl
    {
        ContentTemplate = template
    };
    contentControl.Loaded += (object sender, RoutedEventArgs e) =>
    {
        if (VisualTreeHelper.GetChildrenCount(contentControl) > 0)
        {
            DependencyObject child = VisualTreeHelper.GetChild(contentControl, 0);
            if (child is ContentPresenter contentPresenter && VisualTreeHelper.GetChildrenCount(contentPresenter) > 0)
            {
                 DependencyObject grandChild = VisualTreeHelper.GetChild(contentPresenter, 0);
                 if (grandChild is FrameworkElement frameworkElement)
                 {
                     frameworkElement.DataContext = context;
                 }
            }
        }
    } ;
    return contentControl;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM