Visual Tree Helper

HeinrichBreedt.8522HeinrichBreedt.8522 Heinrich BreedtUSMember

Hi,

Is there an equivalent of WPF's VisualTreeHelper? I need to loop through all the visual elements of a page.

Thank you

Posts

  • RafaelRenzRafaelRenz Rafael Renz USMember

    Hello,
    I am interested in this as well. My situation is the opposite from Heinrich's: I need to access a Page element at an arbitrary distance up the visual tree.

    Thank you.

  • JeremyHerbisonJeremyHerbison Jeremy Herbison CAMember ✭✭

    Bump. Or alternatively, anyone have a good algorithm for searching a Contentpage for all elements of a certain type (eg. Entry)?

  • PeterMillsPeterMills Peter Mills GBMember ✭✭

    I'm after this too :(

  • ReinisLusisReinisLusis Reinis Lusis LVMember

    bump

  • CaioshinCaioshin Fabio Giacomelli ITMember ✭✭

    also interested...xamarin developers!

  • David.RettenbacherDavid.Rettenbacher David Rettenbacher ATMember ✭✭

    I would also need this functionality. I would even be satisfied if container elements like ListView, StackLayout,... shared a simple interface like IChildrenContainer interface which exposes its children.

    It seems all you can do now is to listen at the top container (App?) for DescendantAdded and DescendantRemoved and roll your own DOM.

    @BryanHunterXam
    It would be nice if a Xamarin team-member would describe their current viewpoint on the topic here.

  • TDenisTDenis Denis Toloknov USMember
    edited June 2016

    Hi, my solution, Good luck !

        public static List<T> FindVisualChildren<T>(this VisualElement parentElement, VisualElement whereSearch, string containsStringName = null, List<T> result = null)
        {
            result = result ?? new List<T>();
    
            try
            {
                var props = whereSearch.GetType().GetRuntimeProperties();
                var contProp = props.FirstOrDefault(w => w.Name == "Content");
                var childProp = props.FirstOrDefault(w => w.Name == "Children");
    
                if (childProp == null)
                {
                    if (contProp != null)
                    {
                        var cv = contProp.GetValue(whereSearch) as VisualElement;
                        if (cv != null) FindVisualChildren<T>(parentElement, cv, containsStringName, result);
                    }
                    return result;
                }
    
                IEnumerable v = childProp.GetValue(whereSearch) as IEnumerable;
                foreach (var i in v)
                {
                    if (i is VisualElement) FindVisualChildren<T>(parentElement, i as VisualElement, containsStringName, result);
    
                    if (i is T)
                    {                        
                        if (!string.IsNullOrEmpty(containsStringName))
                        {
                            bool fCheck = false;
                            var fields = parentElement.GetType().GetRuntimeFields().Where(w => w.Name.ToLower().Contains(containsStringName.ToLower())).ToList();
                            foreach(var f in fields)
                            {
                                var fv = f.GetValue(parentElement);
                                if (fv is T && fv == i) { fCheck = true; break; }
                            }
                            if (!fCheck) continue;
                        }
    
                        var ii = (T)i;
                        result.Add(ii);
                    }
                }
                return result;
            }
            catch { return result; }
        }
    
  • CaioshinCaioshin Fabio Giacomelli ITMember ✭✭

    great job, it works like a charm! :-)

  • CaioshinCaioshin Fabio Giacomelli ITMember ✭✭
    edited July 2016

    it's so strange. I noticed that if I put an image inside a button, in this way:

         <Grid>
                    <Button>
                      <Image Source="image.png" VerticalOptions="End" HorizontalOptions="Start"></Image>
                    </Button>
                  </Grid>
    

    with this function I can't retrieve it, so it's not added to the list returned.
    Looking inside the button with the debugger I can't find any reference to the image, because it has no children or content. So, how can I do to retrieve it from the button? I would be sure that the FindVisualChildren function collect all the controls that I'm looking for.

  • TDenisTDenis Denis Toloknov USMember

    I think it's not a good idea to use a button as a container ... I recommend to use iconic font - it's just super! But there are situations in principle, if you do this, I take the time to decide this question ...

Sign In or Register to comment.