tags:

views:

424

answers:

3

Hello,

I have a Silverlight application that is using a DataGrid. Inside of that DataGrid I have a DataTemplate that is defined like the following:

<Grid x:Name="myGrid" Tag="{Binding}" Loaded="myGrid_Loaded">
  <ItemsControl ItemsSource="{Binding MyItems}" Tag="{Binding}">
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <StackPanel Orientation="Horizontal">
          <StackPanel Orientation="Horizontal" Width="138">
            <TextBlock Text="{Binding Type}" />
            <TextBox x:Name="myTextBox" TextChanged="myTextBox_TextChanged" />
          </StackPanel>
        </StackPanel>
      </DataTemplate>
    </ItemsControl.ItemTemplate>
  </ItemsControl>
</Grid>

When a user enters text into the TextBox, I have an event (myTextBox_TextChanged) that must be fired at this point. When that event gets fired, I would like to get the ItemsControl element that is the container for this TextBox. How do I get that ItemsControl from my event handler?

Please note: Because the ItemsControl is in the DataTemplate of DataGrid, I don't believe I can just add an x:Name and reference it from my code-behind. Or is there a way to do that?

Thank you!

+1  A: 

Using a combination of ItemsControl.ItemsControlFromItemContainer and VisualTreeHelper.GetParent you should be able to find your ItemsControl

var txt = sender as TextBox;
var panel1 = VisualTreeHelper.GetParent(txt);
var panel2 = VisualTreeHelper.GetParent(panel1);
var contentPresenter = VisualTreeHelper.GetParent(panel2);
var ic = ItemsControl.ItemsControlFromItemContainer(contentPresenter);

You may also want search the web for VisualTreeHelper Recursive functions to make some of this easier.

bendewey
A: 

I like to have this little extension method in a static class somewhere in my app:-

public static IEnumerable<DependencyObject> Ancestors(this DependencyObject root)
{
    DependencyObject current = VisualTreeHelper.GetParent(root);
    while (current != null)
    {
        yield return current;
        current = VisualTreeHelper.GetParent(current);
    }
}

With that you should be able to do something like this:-

ItemsControl control = ((DependencyObject)sender).Ancestors()
    .TypeOf<ItemsControl>().FirstOrDefault();
AnthonyWJones
A: 

Not sure if this applies but this creates a "toggling button bar" using the same principles.

private void UIClassButton_Click(object sender, RoutedEventArgs e){
 Button SenderButton = (Button)sender;
 ItemsControl SendersItemControl = ItemsControl.ItemsControlFromItemContainer(VisualTreeHelper.GetParent(SenderButton));
 IEnumerable<DependencyObject> DependencyObjectCollection = SendersItemControl.GetContainers();

foreach (ContentPresenter item in DependencyObjectCollection) {
    ContentPresenter UIClassPresenter = (ContentPresenter)item;
    Button UIClassButton = (Button)UIClassPresenter.GetVisualChildren().First();
    if (UIClassButton != SenderButton) {
        VisualStateManager.GoToState(UIClassButton, "Normal", true);
    }
    else {
        VisualStateManager.GoToState(UIClassButton, "Pressed", true);
    }
}
}