Here’s one way to find a named element in a DataTemplate in XAML in Windows 8 XAML.
You might try FindName to discover it doesn’t work. That’s because it’s not
recursive.
So, I created a simple extension method to do the same thing:
public static class FrameworkElementExtensions
{
public static FrameworkElement FindDescendantByName(this FrameworkElement element, string name)
{
if (element == null || string.IsNullOrWhiteSpace(name)) { return null; }
if (name.Equals(element.Name, StringComparison.OrdinalIgnoreCase))
{
return element;
}
var childCount = VisualTreeHelper.GetChildrenCount(element);
for (int i = 0; i < childCount; i++)
{
var result = (VisualTreeHelper.GetChild(element, i) as FrameworkElement).FindDescendantByName(name);
if (result != null) { return result; }
}
return null;
}
}
The code above loops through the children and attempts to match by name.
A simple usage (admittedly, this is stupid and clunky as lists are often
virtualized, but …)
private void Page_Loaded_1(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
for (int i = 0; i < myPeeps.Items.Count; i++)
{
var element = myPeeps.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
if (element != null)
{
var tb = element.FindDescendantByName("tbValue") as TextBlock;
if (tb != null)
{
tb.Text = i.ToString();
}
}
}
}
Given this DataTemplate and Page:
<Page.Resources>
<local:SampleDataSource x:Key="sampleData" />
<DataTemplate x:Key="SampleDataTemplate">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock HorizontalAlignment="Left" Text="{Binding Name}" />
<TextBlock Grid.Row="1" Name="tbValue" />
</Grid>
</DataTemplate>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
DataContext="{StaticResource sampleData}">
<ItemsControl x:Name="myPeeps"
ItemsSource = "{Binding Persons}"
ItemTemplate="{StaticResource SampleDataTemplate}" FontSize="22"/>
</Grid>
And this sample data:
public class Person {
public string Name { get; set; }
}
public class SampleDataSource {
public IEnumerable<Person> Persons { get; private set; }
public SampleDataSource () {
var list = new List<Person>();
list.Add(new Person { Name = "Alex" });
list.Add(new Person { Name = "Betsy" });
list.Add(new Person { Name = "Carla" });
list.Add(new Person { Name = "Donald" });
list.Add(new Person { Name = "Erica" });
list.Add(new Person { Name = "Francis" });
this.Persons = list;
}
}
You’ll get results like this: