0

I want to modify the content in a TabItem of a TabView. And that TabItem uses DataTemplate.

When I am trying to access the children of that item like the following:

        var container = tabview.ContainerFromIndex(tabview.SelectedIndex);
        int count = VisualTreeHelper.GetChildrenCount(container);

I got the ArgumentException: Wrong Parameter Reference on the second line. How should I use VisualTreeHelper to modify it?

Seaky Lone
  • 992
  • 1
  • 10
  • 29

1 Answers1

2

Here is a easy method:

public static T GetChildObject<T>(DependencyObject obj, string name) where T : FrameworkElement
{
    DependencyObject child = null;
    T grandChild = null;

    for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
    {
        child = VisualTreeHelper.GetChild(obj, i);

        if (child is T && (((T)child).Name == name | string.IsNullOrEmpty(name)))
        {
            return (T)child;
        }
        else
        {
            grandChild = GetChildObject<T>(child, name);
        }
        if (grandChild != null)
        {
            return grandChild;
        }
    }
    return null;
}

From your description, you can already get the container of the target element. Let's assume that the element you need is named TargetEle and the type is TextBlock. You can write it like this:

var target = GetChildObject<TextBlock>(container,"TargetEle");

Update

I tested your code and found that you didn't capture the events loaded by the page.

In fact, the SelectionChanged event is fired when the TabView is just created, but the visual tree is not loaded yet, and you can't get the content from it through the code. You can create an IsLoaded property in the page, set it to True when Page Loaded, and determine this property in the SelectionChanged time.

Only when it is True, proceed to the next step.

Thansy
  • 74
  • 4
  • I cannot do this `VisualTreeHelper.GetChildrenCount(obj)`. It gives me an exception described in the question. – Seaky Lone Sep 06 '19 at 13:31
  • Can you describe how you created `TabView`(include XAML code)? Check the Container you get. Is it the expected value? – Thansy Sep 06 '19 at 14:40
  • It is expected. I don't think how it is created matters as I am adding new functionalities to my app. If you really want to see it, it's [here](https://github.com/SeakyLuo/SMPlayer/blob/master/SMPlayer/PlaylistsPage.xaml). – Seaky Lone Sep 06 '19 at 15:39
  • Ah, the `ContainerFromIndex` is null. Although the `SelectedIndex` is expected. – Seaky Lone Sep 07 '19 at 02:01
  • 1
    I tested your code and found that you didn't capture the events loaded by the page. In fact, the `SelectionChanged` event is fired when the TabView is just created, but the visual tree is not loaded yet, and you can't get the content from it through the code. You can create an `IsLoaded` property in the page, set it to True when Page Loaded, and determine this property in the `SelectionChanged` time. Only when it is True, proceed to the next step. – Thansy Sep 07 '19 at 02:21
  • Thank you! This is what I am doing wrong! Please modify your previous answer because that was not the answer I expect but your comment really is. – Seaky Lone Sep 07 '19 at 03:00
  • If possible can you look at this [question](https://stackoverflow.com/questions/57830417/uwp-get-children-from-templated-tabviewitem)? – Seaky Lone Sep 07 '19 at 03:23
  • I will simply say that your `PlaylistControl` is not a child of the `TabViewItem`, which is misleading. You can find your `PlaylistControl` at the TabView level using the recursion method I provided in the answer. Of course, you need named `PlaylistControl`. VisualTreeHelper is not recommended, it is easy to get the code deadlocked. – Thansy Sep 08 '19 at 04:50