Consider following user control:
UserControl1.xaml
<UserControl x:Class="WpfApplication5.UserControl1" 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"><ListBox ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource AncestorType=UserControl}}"><ListBox.ItemTemplate><DataTemplate><Button ContentTemplate="{Binding ItemContentTemplate, RelativeSource={RelativeSource AncestorType=UserControl}}" /></DataTemplate></ListBox.ItemTemplate></ListBox></UserControl>
UserControl1.xaml.cs:
using System.Collections; using System.ComponentModel; using System.Windows; namespace WpfApplication5 { public partial class UserControl1 : INotifyPropertyChanged { public UserControl1() { InitializeComponent(); }
private DataTemplate _itemContentTemplate; public DataTemplate ItemContentTemplate { get { return _itemContentTemplate; } set { _itemContentTemplate = value; OnPropertyChanged("ItemContentTemplate"); } } public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof (IEnumerable), typeof (UserControl1), new PropertyMetadata(default(IEnumerable))); public IEnumerable ItemsSource { get { return (IEnumerable) GetValue(ItemsSourceProperty); } set { SetValue(ItemsSourceProperty, value); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { var handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } } }
And it's usage:
MainWindow.xaml
<Window x:Class="WpfApplication5.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wpfApplication5="clr-namespace:WpfApplication5" Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}"><Window.Resources><DataTemplate x:Key="dataTemplate"><Label Content="{Binding DataContext.Name1, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"></Label></DataTemplate></Window.Resources>
<Grid><wpfApplication5:UserControl1 ItemsSource="{Binding Items}" ItemContentTemplate="{StaticResource dataTemplate}"></wpfApplication5:UserControl1></Grid></Window>
MainWindow.xaml.cs
using System.Collections.Generic; using System.Windows; namespace WpfApplication5 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } public List<Item1> _items = new List<Item1>(){new Item1(){Name1 = "Item 1"}, new Item1(){Name1 = "Item 2"}, new Item1(){Name1 = "Item 3"}}; public List<Item1> Items { get { return _items; } } } public class Item1 { public string Name1 { get; set; } } }Output, all works fine:
Pay attention on following code in MainWindow.xaml:
, RelativeSource={RelativeSource AncestorType=Button}
I set binding source for the Label. Without this code UserControl1 does not work correctly. Let us usesecond version of MainWindow.xaml:
<Window x:Class="WpfApplication5.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wpfApplication5="clr-namespace:WpfApplication5" Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}"><Window.Resources><DataTemplate x:Key="dataTemplate"><Label Content="{Binding Name1}"></Label></DataTemplate></Window.Resources>
<Grid><wpfApplication5:UserControl1 ItemsSource="{Binding Items}" ItemContentTemplate="{StaticResource dataTemplate}"></wpfApplication5:UserControl1></Grid></Window>
Output will be:
Question: how to change UserControl1 so that to eliminate necessity of setting binding source for the Label in the template in order tosecond version of MainWindow.xaml become valid usage of UserControl1? I want get answer on this question because of I think it is wrong to violate incapsulation of UserConrol1. We should be in lack of knowledge what
container is used in UserControl1 to displying items: Button on something else.
See related thread: https://social.msdn.microsoft.com/Forums/vstudio/en-US/ca1da6ba-80da-4947-824a-af667961cc4b/datatemplate-property-in-a-custom-usercontrol?forum=wpf