Reputation: 11
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 a a 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!
Upvotes: 0
Views: 198
Reputation: 11
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;
}
Upvotes: 1