locked
Interact with control in my datatemplate RRS feed

  • Question

  •  Hello,

    I've an ObersvableCollection wich is bind to my ListBox. So, when i add a new item in my collection, with the data binding, we can see a new item in my listbox.

    Until, everything is allright. The problem is when i want to interact with the control in my DataTemplate of my ListBox. This is my DataTemplate :

    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel x:Name="{Binding Path=Name}" MouseEnter="StackPanel_MouseEnter" MouseLeave="StackPanel_MouseLeave">
    
                                <StackPanel Orientation="Horizontal">
                                    <StackPanel>
                                        
                                        <StackPanel Orientation="Horizontal">
                                            <TextBox Width="200" x:Name="{Binding Path=textboxName}" Style="{StaticResource TextBoxStyle}" />
                                            <Image Source="../Images/delete.png" Cursor="Hand" Visibility="Collapsed" />
                                        </StackPanel>
            
                                        <StackPanel Orientation="Horizontal">
                                            <Button Content="Envoi d'image" Width="200" Style="{StaticResource ButtonStyle}" />
                                            <Image Source="../Images/delete.png" Cursor="Hand" Visibility="Collapsed" />
                                        </StackPanel>
                                    </StackPanel>
    
                                    <StackPanel VerticalAlignment="Center">
                                        <Image Source="../Images/add.png" MouseLeftButtonUp="AddDeleteSubject" Cursor="Hand" Visibility="Visible" />
                                    </StackPanel>
                                </StackPanel>
    
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>

     
    Now, i will like when the event AddDeleteSubject is rise (MouseLeftButtonUp), in my method, to get the textbox, the images... control to reach the name property for example.

     Thanks a lot.

    Thursday, April 23, 2009 10:03 AM

Answers

  • A simpler solution would be to declare events of your control within the datatemplate in the XAML itself. something like TextChanged or Loaded event of the TextBox control. When this event is raised you get the instance of the control in the sender object passed as paramter. You can now use this instance or store it in some collections/arrays to be used later.
    Thursday, April 23, 2009 6:51 PM
  • A simpler solution would be to declare events of your control within the datatemplate in the XAML itself.
     

    That is nice and simple! They could even look at the names to determine which text box changed since the names are set through binding:

            void OnTextChanged(object sender, TextChangedEventArgs e)
            {
                TextBox t = sender as TextBox;

                string n = t.Name;

            }

    Thursday, April 23, 2009 7:40 PM

All replies

  • Hopefully, someone else here will see an easier way...but I fear you might need to write quite a bit of code because I don't think methods like FindName and GetTemplateChild will get you the object instantiated from your ItemTemplate.

    You could write a custom derived class of ItemsControl (which is the base of ListBox). This would let you override a few key methods like GetContainerForItemOverride. Since you will be the one creating the containers to hold/display your items in the list, you can do whatever you want like install event handlers on the contained elements, etc.

    I came across a pretty good sample of this technique here: http://www.silverlightshow.net/items/How-to-inherit-from-ItemsControl-and-create-a-UniformGrid-with-containers.aspx.  In the sample, notice how them maintain a dictionary that maps items and their containers. You could do something similar which would let you do a lookup from the item to its container, then dig into the container to access the other elements like the TextBox in your example.

     

    Thursday, April 23, 2009 12:44 PM
  • I forgot about VisualTreeHelper...you can do something like this which is much easier:

            void AddDeleteSubject(object sender, MouseButtonEventArgs e)
            {
                Find(myListBox);
            }

            void Find(DependencyObject root)
            {
                if (root is TextBox)
                {
                    TextBox tb = root as TextBox;
                    // ...
                }

                if (root is Image)
                {
                    Image i = root as Image;
                    //...
                }

                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
                {
                    DependencyObject obj = VisualTreeHelper.GetChild(root, i);

                    Find(obj);
                }
            }

    Thursday, April 23, 2009 3:34 PM
  • A simpler solution would be to declare events of your control within the datatemplate in the XAML itself. something like TextChanged or Loaded event of the TextBox control. When this event is raised you get the instance of the control in the sender object passed as paramter. You can now use this instance or store it in some collections/arrays to be used later.
    Thursday, April 23, 2009 6:51 PM
  • A simpler solution would be to declare events of your control within the datatemplate in the XAML itself.
     

    That is nice and simple! They could even look at the names to determine which text box changed since the names are set through binding:

            void OnTextChanged(object sender, TextChangedEventArgs e)
            {
                TextBox t = sender as TextBox;

                string n = t.Name;

            }

    Thursday, April 23, 2009 7:40 PM
  •  Thanks to all, i test it soon Wink

    Friday, April 24, 2009 9:31 AM