views:

992

answers:

2

I'm trying to create a custom set of classes that can be added to a WPF control through XAML.

The problem I'm having is adding items to the collection. Here's what I have so far.

public class MyControl : Control
{
    static MyControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
    }

    public static DependencyProperty MyCollectionProperty = DependencyProperty.Register("MyCollection", typeof(MyCollection), typeof(MyControl));
    public MyCollection MyCollection
    {
        get { return (MyCollection)GetValue(MyCollectionProperty); }
        set { SetValue(MyCollectionProperty, value); }
    }
}

public class MyCollectionBase : DependencyObject
{
    // This class is needed for some other things...
}

[ContentProperty("Items")]
public class MyCollection : MyCollectionBase
{
    public ItemCollection Items { get; set; }
}

public class MyItem : DependencyObject { ... }

And the XAML.

<l:MyControl>
    <l:MyControl.MyCollection>
        <l:MyCollection>
            <l:MyItem />
        </l:MyCollection>
    </l:MyControl.MyCollection>
</l:MyControl>

The exception is:
System.Windows.Markup.XamlParseException occurred Message="'MyItem' object cannot be added to 'MyCollection'. Object of type 'CollectionTest.MyItem' cannot be converted to type 'System.Windows.Controls.ItemCollection'.

Does any one know how I can fix this? Thanks

A: 

Did you perhaps forget to create an instance of ItemCollection in the constructor of MyCollection, and assign it to Items property? For XAML parser to add items, it needs an existing collection instance. It won't create a new one for you (though it will let you create one explicitly in XAML if the collection property has a setter). So:

[ContentProperty("Items")]
public class MyCollection : MyCollectionBase
{
    public ObservableCollection<object> Items { get; private set; }

    public MyCollection()
    {
         Items = new ObservableCollection<object>();
    }
}
Pavel Minaev
ItemCollection has no public properties. Is there another way of creating it?
Cameron MacFarland
Sorry, I meant no public constructors.
Cameron MacFarland
Good point - looks like it's `internal`, and is really intended to only be used by `ItemsControl`. So either derive from `ItemsControl` (if it makes sense for your class), or use any other XAML-supported collection class, such as `ObservableCollection<T>`. I've updated the example accordingly.
Pavel Minaev
A: 

After more googling, I found this blog which had the same error message. Seems I need to implement IList as well.

public class MyCollection : MyCollectionBase,  IList
{
    // IList implementation...
}
Cameron MacFarland
This is different than your original code - it will add items to `MyCollection` itself, and not to its `Items` property.
Pavel Minaev