---
title: PropertyList
slug: cms-13/docs/propertylist
createdAt: 2026-07-30T20:22:07.892Z
---

:::hint{type="warning"}
**Important**
This topic describes unsupported functionality for complex types in Optimizely Content Management System (CMS) that the implementing developer is responsible for validating to ensure that it works for the item types you want, because supporting complex types as list items brings a whole set of unknowns.  Using `PropertyList<T>` together with complex types requires additional custom functionality to fully ensure data consistency, portability and functionality. This includes, but is not limited to UI, Settings, Export/Import, Permanent link handling and default values.
:::

Use **ContentArea** and **Blocks** for lists of complex objects. Blocks provide a much more controlled object structure for complex types. Define your list model item as a block like:

```csharp
[ContentType(AvailableInEditMode = false, GUID = "38d57768-e09e-4da9-90df-54c73c61b270")]  
public class ContactBlock : BlockData {  
  //block properties  
}
```

The block type then works in lists on other content models:
`public virtual IList<ContactBlock> Contacts { get; set; } `

`PropertyList` defines an editable list of objects. A `Content` model implements a property of type `IList<T>` where `T` is a class with property definitions.

```csharp
public virtual IList<CustomItem> List{ 
  get; 
  set; 
}
```

## Example – list of locations

Implement a list of locations using `PropertyList` with a custom model and editor descriptor.

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/jtM-nKUD3RNES_6VciJuV_2212693c669ef40d172ef9acd1edcc73ae4cfd1dd2c25dd7b5d9a64bfd4f9d1f-property-list.png)

`PropertyList` opens a dialog window for editing items.

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/udHwaNAx3iqkv98j54KRa_f2a13a20fb57b312cbc45f91dbbbc956db5b625d0c4fdfa4cdaa8759f3e3fef9-property-list-dialog.png)

The list contains items with string properties:

- address line1
- address line 2
- city
- country

1. First, define the `Location` model class. It will represent the property item.

:::hint{type="info"}
**Note**
All custom class properties should be `virtual` and have public `get`, `set` methods.
:::

```csharp
using System.ComponentModel.DataAnnotations;

namespace Site.Models.Pages {
  public class Location {
    [Display(Name = "Address line 1")]
    public virtual string AddressLine1 {
      get;
      set;
    }

    [Display(Name = "Address line 2")]
    public virtual string AddressLine2 {
      get;
      set;
    }

    public virtual string City {
      get;
      set;
    }

    public virtual string Country {
      get;
      set;
    }
  }
}
```

2. Register the property definition using a custom property class `LocationsProperty` that sets the generic type to the `Location` item class:

```csharp
using EPiServer.DataAnnotations;
namespace Site.Models.Pages {
  [PropertyDefinitionType]
  public class LocationsProperty : PropertyList<Location> { }
}
```

3. Add the list of locations to the page:

```csharp
using System.ComponentModel.DataAnnotations;
using EPiServer.Core;
using EPiServer.DataAnnotations;
using EPiServer.Cms.Shell.UI.ObjectEditing.EditorDescriptors;
using EPiServer.Shell.ObjectEditing;
using System.Collections.Generic;

namespace Site.Models.Pages {
  /// <summary>
  /// Page with PropertyListDefinition
  /// </summary>
  [ContentType(GUID = "2CDDC73C-83AC-4F35-BA9D-50F285723A96")]
  public class TestPage: PageData {
    [Display(Name = "List of locations")]
    [EditorDescriptor(EditorDescriptorType = typeof (CollectionEditorDescriptor<Location>))]
    public virtual IList<Location> Locations {
      get;
      set;
    }
  }
}
```

## Localize item properties

Translate list item properties the same way as `Content` properties. Use the `DisplayAttribute` and language files to localize property labels. See [Localize the user interface](docId\:aHfkHpVNa60ZqSyt6G5lo).
