none
How to fix Accordion sizing issue while data bound.

    General discussion

  • I need a workaround for Accordion not being able to change its items size if content size changed. I found few workarounds on the web like the following code. However my problem is that I dont know how to access AccordionItem because accordion.Items is bound to a collection of my own objects. How do I get to the AccordionItem to apply the workarounds?

     

            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; });
                    }
                });
            }
    
            public static void UpdateSize2(this AccordionItem item)
            {
                var expandableContentControl = item.GetVisualDescendants().OfType<ExpandableContentControl>().FirstOrDefault();
                if (expandableContentControl != null)
                {
                    var currentPercentage = expandableContentControl.Percentage;
                    expandableContentControl.Percentage = 0;
                    expandableContentControl.UpdateLayout();
                    expandableContentControl.Percentage = currentPercentage;
                }
            } 
    Saturday, February 04, 2012 11:49 AM

All replies

  • in markup:

    <sdk:DataGrid ...
     Loaded="DataGrid_Loaded">
     ...
    </sdk:DataGrid>

    And in the "CodeBehind":

        public partial class MainPage {

    ...
     DataGrid myDataGrid;

            public MainPage() {
                InitializeComponent();
            }

            private void DataGrid_Loaded(object sender, RoutedEventArgs e) {
      myDataGrid = sender as DataGrid;
            }
    ...

        }

    Saturday, February 04, 2012 12:10 PM
  • I dont have data grid. I have accordion bound to an observable collection. I have access to accordion at any time. I need access to AccordionItem objects to apply the workaround.

    Saturday, February 04, 2012 2:05 PM
  • Hi Maxima120,

    However my problem is that I dont know how to access AccordionItem because accordion.Items is bound to a collection of my own objects.

    You may refer a sample in this blog post(e.g. ItemCollection accordionItems = AccordionName.Items).

    Accordion not being able to change its items size if content size changed

    I will suggest you take a look at the discussion in below thread:

    http://social.msdn.microsoft.com/Forums/en-US/silverlightcontrols/thread/525a8a14-7b93-4ce3-8e4d-72ce1552d8f0#5265871f-e29b-44fb-b072-850a65bb88d4

    Best Regards,

    Monday, February 06, 2012 3:37 AM
    Moderator
  • I have it data bound ie accordion.ItemsSource = ObservableCollection<MyObject>. Hence accordion.Items[0].GetType() for example returns MyObject. OK?

    This is why I am asking - how do I get to the AccordionItem objects to apply the workaround NOT using .Items collection (because it has different type).

    Monday, February 06, 2012 7:19 AM
  • Hello mxima120! Did you find a way to fix that anoying sizing problem? If yes, please share with me... this issue is driving me crazy! I'm facing the same problem of yours, in the very same scenario. tks

    Monday, April 23, 2012 11:17 AM
  • yes. I did. but it might not work for you.. I did a lot of tinkering before it started to work for the specific problem I was solving...

    My main objective was to open accordion with first group expanded and then be able to collapse/expand at button click. I cant really tell you much of the details cos I dont remember them. But workable code is below....

            bool isEmptyVisible = true;
            private void ToggleItemsVisibility()
            {
                isEmptyVisible = !isEmptyVisible;
     
                accordion.SelectionSequence = SelectionSequence.Simultaneous;
                accordion.SelectionMode = AccordionSelectionMode.OneOrMore;
     
                accItems.ForEach(i => i.IsEmptyVisible = isEmptyVisible);
     
                var accordionItemList = accordion.GetAllChildrenOfType(typeof(AccordionItem));
                foreach (AccordionItem i in accordionItemList)
                {
                    i.IsSelected = true;
                    i.UpdateSize();
                }
            }
    ...
            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; });
                    }
                });
            }
            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();
            }
    Monday, April 23, 2012 11:26 AM
  • one more thing. the whole solution was wrapped around that IsEmptyVisible property (the button flips it on and off). The property is itself nested in a templated control. And the control is the content of each AccordionItem. And then I had to set each item on first load to make the first group to be opened on the main form load..

    So the following code completes the solution.. I think thats it.. Play with these bits and try to find what suits you as I am not able to provide more help. Cheers

    P.S. var hack - is initially set to the number of all accordion items when it loaded and then counts down to toggle the empty items off and toggle the first group on...

            List<DetailsItemTemplatedControl> accItems = new List<DetailsItemTemplatedControl>();
    
            private void DetailsItem_Loaded(object sender, RoutedEventArgs e)
            {
                DetailsItemTemplatedControl item = sender as DetailsItemTemplatedControl;
     
                hack--;
     
                if (double.IsNaN(item.Height))
                    item.Height = 22.0;
     
                if (item != null)
                    accItems.Add(item);
     
                // this necessary to keep all the groups shut
                accordion.SelectedIndex = -1;
     
                if (hack == 0)
                    this.Dispatcher.BeginInvoke(() =>
                    {
                        ToggleItemsVisibility();
                    });
            }
    Monday, April 23, 2012 11:33 AM