1

I have an ItemsControl defined as below

<ItemsControl Name="PlannerItemControl">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid Name="MainGrid">
             <Grid.ColumnDefinitions>
               <ColumnDefinition Width="200"/>
               <ColumnDefinition Width="Auto" />
               <ColumnDefinition />
             </Grid.ColumnDefinitions>
             <Grid.RowDefinitions>
               <RowDefinition Height="*" />
               <RowDefinition Height="auto" />
             </Grid.RowDefinitions>
             <TextBox Name="test" ></TextBox>
...
...
...
          </Grid>
      </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

In my code behind, I want to loop through all controls in an item

PlannerItemControl.ItemsSource = Plannermod.TimetableModelList;

foreach (var item in PlannerItemControl.Items)
{
  ContentPresenter cp = PlannerItemControl.ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter;
  TextBox tb = FindVisualChild<TextBox>(cp);
  if (tb != null)
  {
                // do something with the textbox
  }
}

public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
{
   if (depObj != null)
   {
     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
     {
       DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
       if (child != null && child is T)
       {
         return (T)child;
       }

       T childItem = FindVisualChild<T>(child);
       if (childItem != null) return childItem;
     }
   }
   return null;
 }      

The problem is the the value of cp is always null although there are items in the itemscontrol since I go inside the foreach loop. Please help

user2837961
  • 1,505
  • 3
  • 27
  • 67
  • These might be helpful: http://stackoverflow.com/questions/16184172/itemcontainergenerator-containerfromitem-returns-null-while-virtualizingstackp , http://stackoverflow.com/questions/6713365/itemcontainergenerator-containerfromitem-returns-null . – goobering Apr 16 '15 at 10:34
  • Maybe you casting incorrectly. Instead of casting to ContentPresenter, cast to FrameworkElement :) or start searching right from ItemsControl. No need for container. Change your FindVisualChild to seek and match DataContext with item – dev hedgehog Apr 16 '15 at 10:55
  • @dev hedgehog the problem comes before FindVisualChild. cp is null. I tried changing the cast to FrameworkElement but that does not help. Also tried to pass item directly to FindVisualChild (with cast as dependencyobject) but that does not work either – user2837961 Apr 16 '15 at 11:02
  • I meant to start the search from ItemsControl. Do not ask for container. You already have the instance of ItemsControl. Use it. – dev hedgehog Apr 16 '15 at 11:05
  • Would 'item' have the data in ItemSource? I am after a control defined in xaml eg the TextBox which does not have a binding – user2837961 Apr 16 '15 at 11:27

1 Answers1

1

I think the problem is in Xaml, but I cant figure out what is for sure. Maybe other styles ? The following code is tested and running well

MainWindow XAML :

<ItemsControl x:Name="PlannerItemControl"  Width="100" Height="100">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid x:Name="MainGrid">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="200"/>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                        <RowDefinition Height="auto" />
                    </Grid.RowDefinitions>
                    <TextBox x:Name="test" ></TextBox>

                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <Button Height="20" Width="100" Click="ButtonBase_OnClick"> Click me!</Button>
            </StackPanel>

MainWindow.cs :

   public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainViewModel();
            PlannerItemControl.ItemsSource = new List<string>() {"a", "b", "c"};

        }



        public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
        {
            if (depObj != null)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                    if (child != null && child is T)
                    {
                        return (T)child;
                    }

                    T childItem = FindVisualChild<T>(child);
                    if (childItem != null) return childItem;
                }
            }
            return null;
        }    

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            foreach (var item in PlannerItemControl.Items)
            {
                ContentPresenter cp = PlannerItemControl.ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter;
                TextBox tb = FindVisualChild<TextBox>(cp);
                if (tb != null)
                {
                    tb.Text = item.ToString();
                    // do something with the textbox
                }
            }
        }
    }
Dragos Stoica
  • 1,753
  • 1
  • 21
  • 42