Getting the control inside a DataTemplate
Here is one way we can get to the Control inside a DataTemplate
lets start with the following XAML in the page
<UserControl x:Class=”SilverlightApplication1.Page”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation“
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml“
xmlns:local=”clr-namespace:SilverlightApplication1;assembly=SilverlightApplication1″
Width=”400″ Height=”300″>
<UserControl.Resources>
<DataTemplate x:Key=”dt”>
<local:Product Margin=”2″/>
</DataTemplate>
</UserControl.Resources>
<Canvas>
<StackPanel>
<ListBox Height=”300″ x:Name=”list1″ Margin=”100,100,100,20″ ItemTemplate=”{StaticResource dt}”/>
<Button Content=”change background” Width=”150″ Click=”Button_Click”></Button>
</StackPanel>
</Canvas>
</UserControl>
So, we have a listbox with an ItemTemplate with a UserControl in it, by default we are going to get a StackPanel for the ItemsPanel.
we are going to bind the listbox to some data
void Page_Loaded(object sender, RoutedEventArgs e)
{
List<ProductData> products = new List<ProductData>();
for (int i = 0; i < 20; i++)
products.Add(new ProductData { ProductID = i, Name = “Product..” + i.ToString() });
list1.ItemsSource = products;
}
The product class is defined like this
public class ProductData
{
public int ProductID { get; set; }
public string Name { get; set; }
}
when we click the button we will change the background of the StackPanel which is in the UserControl(Product)
UserControl(Product) is defined like this
<UserControl x:Class=”SilverlightApplication1.Product”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation“
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml“
>
<StackPanel x:Name=”stackpanel1″ Orientation=”Horizontal”>
<TextBlock Text=”{Binding ProductID}”></TextBlock>
<TextBlock Margin=”10,2,2,2″ Text=”{Binding Name}”></TextBlock>
</StackPanel>
</UserControl>
The Method to get the child of a given type from the VisualTree is below
public T GetChild<T>(DependencyObject obj) where T : DependencyObject
{
DependencyObject child = null;
for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child.GetType() == typeof(T))
{
break;
}
else if (child != null)
{
child = GetChild<T>(child);
if (child != null && child.GetType() == typeof(T))
{
break;
}
}
}
return child as T;
}
The Click event handler for the button is defined like this
private void Button_Click(object sender, RoutedEventArgs e)
{
ListBoxItem lbi;
StackPanel sp = GetChild<StackPanel>(list1) as StackPanel;
for (int i = 0; i < sp.Children.Count; i++)
{
lbi = sp.Children[i] as ListBoxItem;
Product p = GetChild<Product>(lbi);
p.SetBGColor();
}
}
1. we are getting the 1st StackPanel in the VisualTree of the ListBox, this holds all the items of the listbox
2. As the content of the Datatemplate gets wrapped in a ListBoxItem as get that
3. finally we go to the actual Control, in our case the product using the helper function we wrote. once we get the control I am calling a method in that to change the Background color
you can download the code here
I’ve tried to use this example for CellTemplate.
Im my case, the code is like that:
DataGrid dg = new DataGrid();
DataGridTemplateColumn dgtc = new DataGridTemplateColumn();
dgtc.CellTemplate = myGetTemplateFromMyString();
dg.Columns.Add(dgtc);
myGetTemplateFromMyString() retunrs a very simple DataTemplate built from XAML-string and have a TextBlock only.
Is it possible to get the TextBlock from dgtc.CellTemplate in this case ? There is no equivalent of ListBoxItem in DataGrid.
B
Did you try using GetCellContent method?
Of course, not. But I’ll try. Thanks.
Ps.
This subject really inspired me. I appreciate, that you wrote and share small but very helpful “GetChild” method. Thank you.
B.
I haven’t tested this exhaustively, but I think it works – just a simplified version of the GetChild function above.
public T GetChild(DependencyObject obj) where T : DependencyObject
{
DependencyObject child = null;
for( int i = 0; i < VisualTreeHelper.GetChildrenCount( obj ); i++ )
{
child = VisualTreeHelper.GetChild( obj, i );
if( child != null && child.GetType() != typeof( T ) )
{
child = GetChild( child );
}
}
return child as T;
}
Steve,
Thanks for the code, it looks more clean
Thanks for the ideas — Got me past a problem
you are welcome. there are quite a few times, I refered to my own posts