How to Bind to ListBox.ItemsSource inside UserControl

Summary

The post describes two ways of WPF data binding to elements inside WPF user control. Example shows how to establish WPF user control data binding by:

Complete source code is available for download here.

Problem

While working on my project, I needed identical controls and functionality on several windows. The solution was to create WPF user control and use it in all windows.

Control I created contains ListBox , button, textbox and few other controls (panel, border). Creating this user control was easy – define the layout and add standard WPF controls. Step two is using this custom control in windows and other user controls.

Adding user control to other window or user controls is simple:

  • add a reference to a namespace (and assembly if the user control is not in the same assembly as Window where it will be used)
  • add a control to XAML

So, I added my new user control to the window, and next step is to define binding. Type ItemsSource=”{Binding myList}” and the red squiggly line immediately appeared, notifying me that there is no  ItemsSource in my user control.

Binding to Dependency Property in User Control

My user control is derived from UserControl , which does not have ItemsSource property. The first idea is to create a property on user control that exposes ItemsSource property.  The user control will have dependency property of type IEnumerable for ItemsSource, and listbox will have data binding that binds to this property. Consumers of this user control will then be able to bind to this property in XAML, just like standard listbox.

Binding to DataContext of User Control

While reading through UserControl properties, I noticed that I forgot about DataContext property. Second way can be to assign DataContext to my control and then bind ListBox inside my user control. Consumer will bind list to user control DataContext and inside user control, listbox will bind to that DataContext

User Control Example

I decided to test both of solutions to see which one feels better. For test, I created simple user control that contains two listboxes, one will be bound to DataContext, other to dependency property. Here is the code:

<UserControl x:Class="ListboxInUserControlDemo.ListboxInUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myUserControl"
Height="300" Width="500">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="10"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding Path=.}" Grid.Column="0"/>
<ListBox x:Name="listBox2"
ItemsSource="{Binding ElementName=myUserControl, Path=MyItemsSource}"
Grid.Column="2"/>
</Grid>
</UserControl>

In above code, first listbox have ItemsSource bound to current DataContext. Specification Path=. is used to bind to current source (see Binding.Path Property for details). Specifying Path=. is not mandatory, it could be written like this: ItemsSource="{Binding}". I put it here just to remind myself what Path=. actually means.
The second listbox gets ItemsSource from dependency property MyItemsSource. Since ItemsSource is bound to property of this user control, there must be specified element whose property is bound to listbox, so there is: ElementName=myUserControl.

Most of the code behind is code needed to define dependency property:

using System.Collections;
using System.Windows;
using System.Windows.Controls;

namespace ListboxInUserControlDemo
{
/// <summary>
/// Interaction logic for ListboxInUserControl.xaml
/// </summary>
public partial class ListboxInUserControl : UserControl
{
public static readonly DependencyProperty MyItemsSourceProperty;

static ListboxInUserControl()
{
ListboxInUserControl.MyItemsSourceProperty =
DependencyProperty.Register("MyItemsSource",
typeof(IEnumerable), typeof(ListboxInUserControl));
}

public IEnumerable MyItemsSource
{
get
{
return (IEnumerable)GetValue(ListboxInUserControl.MyItemsSourceProperty);
}
set
{
SetValue(ListboxInUserControl.MyItemsSourceProperty, value);
}
}

public ListboxInUserControl()
{
InitializeComponent();
}
}
}

Consuming User Control in Window

Now we have user control defined. Next step is to put it into window and test behavior. To see difference between binding methods, example will contain two copies of the user control. One will bind to DataContext, while second will bind to dependency property. On each copy of user control, one listbox will show data, while other will be empty.

<Window x:Class="ListboxInUserControlDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lbUserControl="clr-namespace:ListboxInUserControlDemo"
Title="Window1" Height="400" Width="550"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<TabControl>
<TabItem Header="DataContext binding" >
<lbUserControl:ListboxInUserControl DataContext="{Binding TestList}"/>
</TabItem>
<TabItem Header="Dependency Property Binding">
<lbUserControl:ListboxInUserControl MyItemsSource="{Binding TestList}"/>
</TabItem>
</TabControl>
</Grid>
</Window>

Window contains TabControl with two TabItems. Each TabItem have one ListboxInUserControl.

There is nothing special in code behind of this window, standard constructor and initialization for TestList property:

using System.Collections.Generic;
using System.Windows;

namespace ListboxInUserControlDemo
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}

List<string> _testList;
public List<string> TestList
{
get
{
if (_testList == null)
InitList();
return _testList;
}
}

private void InitList()
{
_testList = new List<string>();
_testList.Add("Lorem ipsum dolor sit amet,");
_testList.Add("consectetur adipiscing elit. ");
_testList.Add("Duis mollis egestas ornare. ");
_testList.Add("Cras diam est, sollicitudin ");
_testList.Add("quis vulputate sed, lacinia.");
_testList.Add("Phasellus lorem nunc, fringilla eget posuere");
_testList.Add("sed, tincidunt nec felis. Ut non dui ut");
_testList.Add("metus auctor scelerisque quis ornare leo.");
_testList.Add("Integer eget purus tellus. Nullam ut urna dui.");
_testList.Add("Quisque sed enim magna, sed.");
}
}
}


So, let’s see what happens when I run this code.
The first user control on first TabItem binds to DataContext to TestList the property of a window. Left listbox in user control binds to that DataContext and it will show contents of TestList. Right listbox will be empty since there is no binding to the dependency property MyItemsSource.
Second user control binds dependency property MyItemsSource to TestList property of the window but does not bind DataContext. On this tab left listbox will be empty, and right listbox will show contents of TestList.

There it is. Two ways to databind to ListBox inside the user control. This, of course, works for all types of controls.
I prefer databinding with DataContext. Defining DependencyProperty adds lots of code in codebehind but does not save anything when you consume UserControl.

The complete code is available for download here.