3

I have a very simple usercontrol:

<UserControl x:Class="PointOfSale.UserControls.HousesGrid"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">

<ItemsControl x:Name="LayoutRoot" ItemsSource ="{Binding PopularHouses}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="5"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ToggleButton
                Content="{Binding FormattedPanelTimeRemaining}"
                Style="{StaticResource MetroToggleButtonStyle}"
                Height="45"
                Width="80"
                VerticalAlignment="Center"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

As you can see the ItemSource property is bound to the PopularHouses property on the ViewModel of the parent. This works great. However, what I want to do is set the ItemSource of the LayoutRoot element to a different property at the point on the parent form where the control is inserted in the XAML.

The end result should then be multiple instances of this user control, bound to several different properties on the parent's datacontext.

Could someone explain how to implement this?

IntoNET
  • 456
  • 2
  • 14
  • 1
    You realize you are thinking backwards, right? Why change the property you are bound to, and not make your viewmodel generic? – Mishka Aug 03 '17 at 15:03
  • 1
    If you want `ItemsSource` to be *binde-able* from outside you can expose it as dependency property of user control and simply bind `LayoutRoot.ItemsSource` to it. See [this answer](https://stackoverflow.com/a/5700294/1997232). – Sinatr Aug 03 '17 at 15:04

1 Answers1

1

You just have to bind your UserControl's DataContext to the datacontext of the first ContentControl using RelativeSource.

 DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type ContentControl}}}"

I have made the following sample:

The mainwindow XAML

<Window x:Class="WpfDataContext.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfDataContext"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <local:UserControl1/>
    </Grid>
</Window>

We set its datacontext to Self just for the purpose of this sample. In codebehind we define a simple property to show how it works:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    public string SomeString { get; set; } = "Hello";
}

Then, the usercontrol XAML:

<UserControl x:Class="WpfDataContext.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type ContentControl}}}">
    <Grid>
        <TextBlock Text="{Binding SomeString}"/>
    </Grid>
</UserControl>

Note how we bind its DataContext property since this is the key.

I use a Textblock for simplicity, but the principle applies for your case also

taquion
  • 2,667
  • 2
  • 18
  • 29