Search code examples
silverlightc#-4.0silverlight-toolkitsilverlight-5.0

Silverlight Accordion. How to shrink to content on data bound collection


I have Accordion which is bound to ObservableCollection. I need to apply workaround to make Accordion resize its children to the content (ie if an item has been deleted from the bound collection I need the accordion to shrink, and if added - to expand).

However all the workaround I found use AccordionItem objects. They all have AccordionItem items set in XAML so their accordion.Items are collections of AccordionItem objects.

Although I am binding to myObject they are placed in AccordionItem object in the ItemContainerStyleTemplate. The only thing I need is to access that AccordionItem somehow. If I try something like accordion.Items[0].GetType() it returns myObject.

So the question is - how do I access AccordionItem object from data bound Accordion?

The workaround I wanted to try: (EDIT: It does work as I needed)

    public static void UpdateSize(this AccordionItem item)
    {
        item.Dispatcher.BeginInvoke(
        delegate
        {
            if (!item.IsLocked && item.IsSelected)
            {
                item.IsSelected = false;
                item.InvokeOnLayoutUpdated(delegate { item.IsSelected = true; });
            }
        });
    }

Solution

  • I've had to do similar things to Accordions, and the only way I was able to get down to the AccordionItems was by walking the visual tree.

    Here's how I did it: Given these extension methods :

    public static IEnumerable<DependencyObject> GetAllChildrenOfType(this DependencyObject depObject, Type t, bool recursive = true)
    {
        List<DependencyObject> objList = new List<DependencyObject>();
    
        var childrenList = depObject.GetChildren();
    
        foreach (DependencyObject i in childrenList)
        {
            Type ct = i.GetType();
            if (ct == t)
                objList.Add(i);
    
                if (recursive)
                    objList.AddRange(i.GetAllChildrenOfType(t));
        }
        return objList.ToArray();
    }
    
    public static IEnumerable<DependencyObject> GetChildren(this DependencyObject depObject)
    {
         int count = depObject.GetChildrenCount();
         for (int i = 0; i < count; i++)
         {
             yield return VisualTreeHelper.GetChild(depObject, i);
         }
    }
    

    Now you can get all the AccordionItems in a given Accordion:

    var accordionItemList = myAccordion.GetAllChildrenOfType(typeof(AccordionItem));
    
    foreach (AccordionItem i in accordionItemList)
    {...}
    

    This may be a bit more complicated than needed, in my instance I had an accordion within the accordion, which made things difficult in the end.