How to pass data from MainWindow to a User Control that’s inside the MainWindow?

A UserControl should never have a “private” view model, as you assign it to the DataContext in the UserControl’s XAML. It should instead expose dependency properties that could be bound to properties of an externally provided view model object.

Declare an ItemsSource property like this:

public partial class UserControl1 : UserControl
{
    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register(
            nameof(ItemsSource), typeof(IEnumerable), typeof(UserControl1));

    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public UserControl1()
    {
        InitializeComponent();
    }
}

And bind the ListView like this:

<UserControl ...>
    ...
    <ListView ItemsSource="{Binding ItemsSource,
                            RelativeSource={RelativeSource AncestorType=UserControl}}">
        ...
    </ListView>
    ...
</UserControl>

When you use the UserControl, bind the property to a view model property:

<TabItem Header="UC1">
    <local:UserControl1 ItemsSource="{Binding OrderList}"/>
</TabItem>

The last XAML snippet assumes that the object in the UserControl’s DataContext has a OrderList property. This would automatically happen when the TabControl is bound to a collection of view model objects with that property.


Alternatively, let the elements in the UserControl’s XAML directly bind to the properties of the object in the inherited DataContext.

<UserControl ...>
    ...
    <ListView ItemsSource="{Binding OrderList}">
        ...
    </ListView>
    ...
</UserControl>

Your control would not have to expose additional bindable properties, but it would only work with DataContext objects that actually provide the expected source properties.

Leave a Comment