views:

1902

answers:

2

I'm using the Silverlight Toolkit's Accordion control. I wanted to create a list of controls that I could load into the accordion and replace on the fly if needed. So here is what I did:

  1. Create a class to hold the header and content of each accordian item.

    public class AccordionViewItem { public AccordionViewItem() { ItemsControlContent = new ObservableCollection(); ItemsControlContent.Add(new StackPanel()); }

    public string Header { get; set; }
    public FrameworkElement Content 
    {
        get { return ItemsControlContent[0]; }
        set { ItemsControlContent[0] = value; }
    }
    
    
    public ObservableCollection<FrameworkElement> ItemsControlContent { get; set; }
    

    }

I've got some extra properties in here that aren't needed until I present my problem. For now I just wanted to show the Header and ItemsControlContext properties.

  1. Created the Accordian control.

    <layoutToolkit:Accordion x:Name="AccordionHost" ItemsSource="{Binding Path=Panels}" SelectionMode="One" VerticalAlignment="top" HorizontalAlignment="Center" >
        <layoutToolkit:Accordion.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding Header}" />
                </StackPanel>
            </DataTemplate>
        </layoutToolkit:Accordion.ItemTemplate> 
        <layoutToolkit:Accordion.ContentTemplate>
            <DataTemplate>
                <ItemsControl ItemsSource="{Binding Path=ItemsControlContent}" />
            </DataTemplate>
        </layoutToolkit:Accordion.ContentTemplate>
    </layoutToolkit:Accordion>
    

So if I set the datacontext and send in a list of AccordionViewItems I can get a functioning Accordion, but I really wanted to have my AccordionView Item look like:

public class AccordionViewItem
{
    public AccordionViewItem()
    {
        Content = new StackPanel();
    }

    public string Header { get; set; }
    public FrameworkElement Content { get; set; }
}

So I created a custom control called ItemControl:

<UserControl x:Class="ECAPortal.Client.Common.Controls.ItemControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="400"
    Width="300" >
    <Grid x:Name="LayoutRoot" Background="White">
        <ItemsControl x:Name="itemsControlLoader" />
    </Grid>
</UserControl>

Code Behind:

public partial class ItemControl : UserControl
{
    private ObservableCollection<FrameworkElement> m_controls = new ObservableCollection<FrameworkElement>();

    public ItemControl()
    {
        m_controls.Add(new StackPanel());

        InitializeComponent();

        this.Loaded += new RoutedEventHandler(ItemControl_Loaded);
    }

    void ItemControl_Loaded(object sender, RoutedEventArgs e)
    {
        itemsControlLoader.ItemsSource = m_controls;
    }

    public FrameworkElement ItemSource
    {
        get { return m_controls[0]; }
        set { m_controls[0] = value; }
    }
}

Then change the Accordion to use the new control:

    <layoutToolkit:Accordion x:Name="AccordionHost" ItemsSource="{Binding Path=Panels}"     SelectionMode="One" Margin="0,50" Width="740" VerticalAlignment="top"     HorizontalAlignment="Center" >
        <layoutToolkit:Accordion.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding Header}" />
                </StackPanel>
            </DataTemplate>
        </layoutToolkit:Accordion.ItemTemplate> 
        <layoutToolkit:Accordion.ContentTemplate>
            <DataTemplate>
                <controls:ItemControl ItemSource="{Binding Content}" />
            </DataTemplate>
        </layoutToolkit:Accordion.ContentTemplate>
    </layoutToolkit:Accordion>

But I get the following error after the ItemControl constructor is run:

AG_E_PARSER_BAD_PROPERTY_VALUE [Line: 1 Position: 197]

Any idea why I'm getting this error? Is there another way to load in a control dynamically? I'm trying to use as little code in the code behind as I can (MVVM). Any ideas would be great.

Thanks,

Jamin Roth

A: 

You sould have to use in place of

Thanks Nisheeth Tak

Nisheeth
A: 

I found a simple solution. You can use the ContentPresenter. So you can use it like the custom control should have. So you can replace:

<controls:ItemControl ItemSource="{Binding Content}" />

With:

<ContentPresenter Content="{Binding Content}" />

not only does it load your content dynamically, but you can stretch the width unlike with the ItemsControl.

Jamin

related questions