I am trying to create a usercontrol in WPF that includes a content collection and struggling to get the binding to work correctly on the sub elements. I already looked at this example, but I'm one level more deeply nested that this and so this solution didn't help: Data Binding in WPF User Controls
Here is my UserControl:
<UserControl x:Class="BindingTest.MyList"
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"
x:Name="uc">
<Grid>
<ListView Grid.Row="1" ItemsSource="{Binding Items, ElementName=uc}">
<ListView.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Text}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</UserControl>
And the codebehind:
[ContentProperty("Items")]
public partial class MyList : UserControl {
public MyList() {
InitializeComponent();
}
public ObservableCollection<MyItem> Items { get; set; } = new ObservableCollection<MyItem>();
}
public class MyItem : DependencyObject {
public string Text {
get {
return (string)this.GetValue(TextProperty);
}
set {
this.SetValue(TextProperty, value);
}
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MyItem), new PropertyMetadata());
}
And then how I'm using it in the app:
<Window x:Class="BindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BindingTest"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="{Binding Val1, Mode=TwoWay}" />
<local:MyList Grid.Row="1">
<local:MyItem Text="{Binding Val1}" />
<local:MyItem Text="Two" />
<local:MyItem Text="Three" />
</local:MyList>
<ListView Grid.Row="2">
<ListViewItem Content="{Binding Val1}" />
<ListViewItem Content="Bravo" />
<ListViewItem Content="Charlie" />
</ListView>
</Grid>
</Window>
And finally my window:
public partial class MainWindow : Window, INotifyPropertyChanged {
public MainWindow() {
InitializeComponent();
}
string _val1 = "Foo";
public string Val1 {
get { return _val1; }
set {
_val1 = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Val1"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
The problem I'm encountering is that the first "MyItem" in the user control ends up displaying blank text, whereas the first ListViewItem in the stock control displays Foo as you would expect.
I understand this is because in the MyList control the DataTemplate switches the DataContext for each item in the collection, but no matter what I try in the binding expressions, either in the window or the user control, I can't get it to bind to Val1 on the window correctly.
What am I doing wrong?