views:

540

answers:

3

I need to use an Accordion to display some totals on a LOB application we are building.

If I place the Accordion in XAML all works fine and the state of the icon (>) is correct and pointing to the right. On Mouse entering the AccordionItem we do not have a visual state change.

If I dynamically add AccordionItems on a Button Click (to simulate async data call returning) the state of the icon is not the same and on MouseEnter it "corrects" itself by executing a visual state change. *You may need to click "Add 3 Accordion Items" twice.

If I dynamically add an Accordion on a Button click with AccordionItems it works fine. Below is my sample Application.

So what do I need to do to get the Accordion to add AcordionItems at runtime and be in the correct state as per when using XAML?

XAML

 <Grid x:Name="LayoutRoot" Background="Black" >
  <StackPanel x:Name="TheStackPanel">
     <Button Content="Create Accordion" Click="CreateAccordionItems"></Button>
     <Button Content="Add 3 Accordion Items" Click="AddAccordionItems"></Button>
     <Grid Background="Pink">
        <layoutToolkit:Accordion SelectionMode="ZeroOrMore" x:Name="TestAccordion" Margin="10,10,10,10" HorizontalAlignment="Stretch"  >
           <layoutToolkit:AccordionItem Content="Content - 1" Header="Header - 1">
           </layoutToolkit:AccordionItem>
           <layoutToolkit:AccordionItem Content="Content - 2" Header="Header - 2">
           </layoutToolkit:AccordionItem>
           <layoutToolkit:AccordionItem Content="Content - 3" Header="Header - 3">
           </layoutToolkit:AccordionItem>
        </layoutToolkit:Accordion>
     </Grid>
  </StackPanel>

 public partial class MainPage : UserControl

{ private int count = 0; public MainPage() { // Required to initialize variables InitializeComponent(); //TestAccordion.ExpandDirection = ExpandDirection.Down; }

  private void AddAccordionItems( object sender, RoutedEventArgs e )
  {
     AddToAccordion( 3, TestAccordion );
  }

  private void AddToAccordion( int size, Accordion _Accordion )
  {
     for( int i = 0; i < size; i++ )
     {
        AccordionItem accordionItem = new AccordionItem( );
        accordionItem.Header = "Item " + count.ToString( );
        count++;
        _Accordion.Items.Add( accordionItem );
        Grid aGrid = new Grid( );
        TextBlock tb = new TextBlock( );
        tb.Text = accordionItem.Header as string;
        aGrid.Children.Add( tb );
        accordionItem.Content = aGrid;
        //accordionItem.IsEnabled = true;
        accordionItem.IsSelected = true;
     }
  }

  private void CreateAccordionItems( object sender, RoutedEventArgs e )
  {
     Accordion accordion = new Accordion( );
     accordion.HorizontalContentAlignment = HorizontalAlignment.Stretch;
     TheStackPanel.Children.Add( accordion );
     AddToAccordion( 10, accordion );
  }

}

+1  A: 

If you take a look at the source code for the Accordian control you'll see that it uses the InteractionHelper.UpdateVisualState to set its correct state after events.

public void UpdateVisualStateBase(bool useTransitions)
{
    if (!this.Control.IsEnabled)
    {
        VisualStates.GoToState(this.Control, useTransitions, new string[] { "Disabled", "Normal" });
    }
    else if (this.IsReadOnly)
    {
        VisualStates.GoToState(this.Control, useTransitions, new string[] { "ReadOnly", "Normal" });
    }
    else if (this.IsPressed)
    {
        VisualStates.GoToState(this.Control, useTransitions, new string[] { "Pressed", "MouseOver", "Normal" });
    }
    else if (this.IsMouseOver)
    {
        VisualStates.GoToState(this.Control, useTransitions, new string[] { "MouseOver", "Normal" });
    }
    else
    {
        VisualStates.GoToState(this.Control, useTransitions, new string[] { "Normal" });
    }
    if (this.IsFocused)
    {
        VisualStates.GoToState(this.Control, useTransitions, new string[] { "Focused", "Unfocused" });
    }
    else
    {
        VisualStates.GoToState(this.Control, useTransitions, new string[] { "Unfocused" });
    }
}

Since the method is marked internal on the Accordian control and the InteractionHelper is a private variable, your best bet is to figure out which of the states you're adding the control in and then tell the control to go to that state (without a transition) before addig it to the visual tree. This is why the MouseOver is "fixing" it.

Bryant
How did you go to finding out the source code for the control. This was very helpful. And there is no way to change it?
WmasterJ
A: 

Call TestAccordion.UpdateLayout(); after adding the items... may be

kbr
A: 

Can you bind the accordian Items to an ObservableCollection?

Mark Cooper