locked
Accessing Elements in ItemsControl.ItemTemplate

    Question

  • I have a Windows Store 8.1 app with an ItemsControl and DataTemplate. I want to be able to access the elements in the DataTemplate after binding. I have found multiple postings involving FindName and VisualTreeHelper. I cannot use FindName because it is not available for Windows Store apps. I have been unable to get any of the postings or examples to work. In another project of mine, I used the ContentTemplateRoot() method of the PivotItem, which is basically what I want here, except I am not using a Pivot control. Can anybody help me figure out how to access the elements in a DataTemplate? Thanks.

    Nathan Sokalski njsokalski@hotmail.com http://www.nathansokalski.com/

    Sunday, October 12, 2014 1:38 AM

Answers

  • I tried keeping track of the index of the focused TextBox and adding a Loaded event handler for each TextBox, and in that Loaded event calling the Focus method if it is the right one. So far it works, so I guess it might be the best I can get for my scenario.

    Nathan Sokalski njsokalski@hotmail.com http://www.nathansokalski.com/

    Monday, October 20, 2014 6:43 PM

All replies

  • Wait until the ItemsControl has been fully loaded, i.e. handle the Loaded event of the Page or the ItemsControl, and use a helper method that traverses the visual tree.

    Here is an example that access the TextBlock element in the DataTemplate of an ItemsControl:

        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
                ic.ItemsSource = new List<string> { "a", "b", "c" };
    
                this.Loaded += MainPage_Loaded;
            }
    
            void MainPage_Loaded(object sender, RoutedEventArgs e)
            {
                foreach (var item in ic.Items)
                {
                    ContentPresenter container = ic.ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter;
                    if (container != null)
                    {
                        TextBlock txtBlock = FindVisualChild<TextBlock>(container);
                        if (txtBlock != null)
                        {
                            txtBlock.FontStyle = Windows.UI.Text.FontStyle.Italic;
                        }
                    }
                }
            }
    
            childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                    if (child != null
                        && child is childItem)
                        return (childItem)child;
                    else
                    {
                        childItem childOfChild = FindVisualChild<childItem>(child);
                        if (childOfChild != null)
                            return childOfChild;
                    }
                }
                return null;
            }
    
        }
    

     
    <ItemsControl x:Name="ic">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}" FontSize="20"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
    Please remeber to mark helpful posts as answer and/or helpful.
    Sunday, October 12, 2014 12:58 PM
  • Unfortunately, that would not work for me. Because the ItemsControl will be bound and rebound multiple times during the app but MainPage.Loaded only occurs once, it is pointless to do anything in there for this (other than initialization). Will the Loaded event of the ItemsControl get called every time I set ItemsSource? If I add a Loaded event for the TextBox, will that Loaded event get raised for each TextBox each time I set ItemsSource? But MainPage.Loaded only gets called once, so that will not work for me.

    Nathan Sokalski njsokalski@hotmail.com http://www.nathansokalski.com/

    Monday, October 20, 2014 2:24 AM
  • I tried keeping track of the index of the focused TextBox and adding a Loaded event handler for each TextBox, and in that Loaded event calling the Focus method if it is the right one. So far it works, so I guess it might be the best I can get for my scenario.

    Nathan Sokalski njsokalski@hotmail.com http://www.nathansokalski.com/

    Monday, October 20, 2014 6:43 PM