Search code examples
c++uwpwinrt-xamlc++-cx

How can I get an element from within a ListViewItem's ItemTemplate?


I have a ListView that uses a custom ItemTemplate (doesn't everyone?):

<ListView>
  <!-- ... -->
  <ListView.ItemTemplate>
    <DataTemplate x:DataType="x:String">
      <MyGreatControl Thing="{x:Bind}" />
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

MyGreatControl today has extensive keyboard handling code built-in, but due to some refactoring, I need to move the actual handlers to the ListView itself. However, I don't want to move all of the code in MyGreatControl to the ListView (for many reasons).

If I have an arbitrary ListViewItem (which, for example, I can get from an event handler), how can I access the MyGreatControl instance in its DataTemplate?

MyGreatControl^ GetMyGreatControlFromListViewItem(ListViewItem^ listViewItem) {
    // ???
}

Disclaimer: I work for Microsoft.


Solution

  • You want to use ContentTemplateRoot!

    MyGreatControl^ GetMyGreatControlFromListViewItem(ListViewItem^ listViewItem) {
      return safe_cast<MyGreatControl^>(listViewItem->ContentTemplateRoot);
    }
    

    This also works for any arbitrary element—if you have a StackPanel, for example, ContentTemplateRoot will return the StackPanel instance you want:

    <ListView.ItemTemplate>
      <DataTemplate x:DataType="x:String">
        <StackPanel><!-- This is what you get! -->
          <TextBlock Text="{x:Bind}" />
          <Button Content="Foo" IsTabStop="False" />
        </StackPanel>
      </DataTemplate>
    </ListView.ItemTemplate>
    

    You can then use normal visual tree navigation to find Children, etc.