How to create Dependency Properties for Collections


Hello, today I’m going to write about creation of dependency properties that work with collections.

In case you don’t remember what dependency properties are, you should read this article.

Imagine that you are creating control that has property that accepts collection:


public class CustomControl : Control
{ 
    public IEnumerable<string> Items { get; set; } 
}

If you want property Items to act as binding target you must change it to be dependency property:

public class CustomControl : Control
{
     public static readonly DependencyProperty ItemsProperty = 
                 DependencyProperty.Register("Items", typeof (IEnumerable<string>), typeof (CustomControl), new PropertyMetadata(new List<string>())); 

     public IEnumerable<string> Items 
     { 
         get { return (IEnumerable<string>) GetValue(ItemsProperty); } 
         set { SetValue(ItemsProperty, value); } 
     } 
}
As you can see, we changed this property to dependency property and supplied new instance of List class as default parameter. As it turned out, this default value will be used on class level (i.e. it will be created only once and each instance of CustomControl will have reference to the same collection). Therefore, we need one modification:
public class CustomControl : Control
{
     public CustomControl() 
     {
          Items = new List<string>(); 
     }
}

Now you can use this control and supply value for Items property via binding:

<Grid> 
   <DependencyPropertiesCollection:CustomControl Items="{Binding ItemsSource}"/> 
</Grid>

Currently this control has one limitation – Items property can’t be filled directly in XAML like this code does:

<Grid>
   <DependencyPropertiesCollection:CustomControl> 
       <DependencyPropertiesCollection:CustomControl.Items> 
              <System:String>Item 1</System:String> 
              <System:String>Item 2</System:String> 
              <System:String>Item 3</System:String> 
              <System:String>Item 4</System:String> 
              <System:String>Item 5</System:String>
       </DependencyPropertiesCollection:CustomControl.Items>
  </DependencyPropertiesCollection:CustomControl> 
</Grid>
To fix this, you need to change property type from IEnumerable to IList:
public class CustomControl : Control 
{ 
      public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof (IList), typeof (CustomControl), new PropertyMetadata(new List<string>())); 

      public IList Items 
      { 
           get { return (IList)GetValue(ItemsProperty); } 
           set { SetValue(ItemsProperty, value); }
      } 

      public CustomControl() 
      {
            Items = new List<string>(); 
      } 
}

It seems that XAML parser can’t create instance of IEnumerable implementation implicitly.

That’s it. Hope this article will help you if you need to create dependency property that works with collections types.

Advertisements