You can bind to public properties, sub-properties, as well as indexers of any common language runtime (CLR) object. The binding engine uses CLR reflection to get the values of the properties. Alternatively, objects that implement ICustomTypeDescriptor or have a registered TypeDescriptionProvider also work with the binding engine.

See the next section for more information about how to implement a class that can serve as a source object.

ADO.NET data

You can bind to ADO.NET objects such as DataTable. The ADO.NET DataView implements IBindingList, providing change notifications that the binding engine listens for.

If you do not implement INotifyPropertyChanged, then you must arrange for your own notification system to make sure that the data used in a binding stays current. You can provide change notifications by supporting the PropertyChanged pattern for each property that you want change notifications for. To support this pattern, you define a PropertyNameChanged event for each property, where PropertyName is the name of the property. You raise the event every time the property changes.

If your source object implements a proper notification mechanism target updates happen automatically. If for any reason your source object does not provide the proper property changed notifications, you have the option to use the UpdateTarget method to update the target property explicitly.

Other Characteristics

The following list provides other important points to note:

If you want to create the object in XAML, the class must have a default constructor. In some .NET languages, such as C#, the default constructor might be created for you.

The properties you use as source properties for a binding must be public properties of your class. Explicitly defined interface properties cannot be accessed for binding purposes, nor can protected, private, or virtual properties that have no base implementation.

You cannot bind to public fields of a CLR class.

The type of the property declared in your class is the type that is passed to the binding. However, the type ultimately used by the binding depends on the type of the binding target property, not of the source property. If there is a difference in type, you might want to write a converter to handle how your custom property is initially passed to the binding. For more information, see IValueConverter.

You can use an entire object as the source for a binding. This can be done by specifying the object as the binding source using the Source or the DataContext property, and then providing no path beyond a blank binding declaration: {Binding}. Scenarios in which this is useful include binding to objects that are of type string, binding to objects with multiple properties you are interested in, or binding to collection objects. For an example of binding to an entire collection object, see How to: Use the Master-Detail Pattern with Hierarchical Data.

Note that you may need to apply custom logic so that the data is meaningful to your bound target property. The custom logic may be in the form of a custom converter (if default type conversion does not exist) or a DataTemplate. For more information about converters, see the Data Conversion section of the Data Binding Overview. For more information about data templates, see Data Templating Overview.

Often, the object you want to use as the source is a collection of multiple custom objects, each of which represents a data object that serves as the source for one instance of a repeated binding. For instance, you might have a CustomerOrders collection consisting of CustomerOrder objects, where your application iterates over the collection to determine how many orders exist and the data contained in each.

You can enumerate over any collection that implements the IEnumerable interface. However, to set up dynamic bindings so that insertions or deletions in the collection update the UI automatically, the collection must implement the INotifyCollectionChanged interface. This interface exposes an event that must be raised whenever the underlying collection changes.

WPF never binds directly to a collection. If you specify a collection as a data source, WPF actually binds to the collection's default view. For information about default views see Data Binding Overview.

If you have an advanced scenario and want to implement your own collection, consider using IList, which provides a non-generic collection of objects that can be individually accessed by index and thus the best performance.

The following table summarizes what property types can be bound to in an application that is executing in either full trust or partial trust:

Property type

(all access modifiers)

CLR property

CLR property

Dependency property

Dependency

property

Trust level

Full trust

Partial trust

Full trust

Partial trust

Public class

Yes

Yes

Yes

Yes

Private class

Yes

No

Yes

Yes

This table describes the following important points about permission requirements in data binding:

For CLR properties, data binding works as long as the binding engine is able to access the source property using reflection. Otherwise, the binding engine issues a warning that the property cannot be found and uses the fallback value or the default value, if it is available.

You can always bind to dependency properties.

The permission requirement for XML binding is similar: in a partial-trust sandbox, XmlDataProvider fails when it does not have permissions to access the given data.