I'm trying to learn about DependencyProperty. To do so I want to create a new UserControl
which displays a list.
The location of this list must exist in the parent as a property. For this, I only have MainWindow
, MainWindowViewModel (these are the parent) and the UserControl
(the child) (which is currently using code behind).
In my MainWindow I have
<Grid>
<uc:RecentList MessageList="{Binding Messages}" />
</Grid>
And in the code behind
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
And the ViewModel
public MainWindowViewModel()
{
this.Messages = new ObservableCollection<string>();
this.Messages.Add("Item 1");
this.Messages.Add("Item 2");
this.T = "hi";
}
public ObservableCollection<string> Messages { get; set; }
In the UserControl
I have
<Grid>
<ListView ItemsSource="{Binding MessageList}"></ListView>
<TextBlock Text="I'm such text to verify this control is showing" />
</Grid>
And the code behind is
public static readonly DependencyProperty MessageListProperty =
DependencyProperty.Register(
"MessageList", typeof(IEnumerable<string>), typeof(RecentList));
public IEnumerable<string> MessageList
{
get { return (IEnumerable<string>)GetValue(MessageListProperty); }
set { SetValue(MessageListProperty, value); }
}
The issue I have is the binding is not working. I can see this in the Output Window, with the Error:
Error 40 : BindingExpression path error: 'MessageList' property not found on 'object' ''MainWindowViewModel' (HashCode=26034861)'. BindingExpression:Path=MessageList; DataItem='MainWindowViewModel' (HashCode=26034861); target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
I understand the issue but I am confused by it. It's looking in the right place (in the MainWindowViewModel) but it is looking I don't understand why the UserControl
is looking for the MessageList
in the MainWindowViewModel
. I guess it's because that is where I set the datacontext but, I also thought it that if I added this.DataContext = this;
to the UserControl's constructor then it's wrong (I've tried it, it didn't work either).
Updating my UserControl
to
<ListView ItemsSource="{Binding MessageList, RelativeSource={RelativeSource Mode=TemplatedParent}}"></ListView>
Helps in the sense I don't get the error message, but I also don't see the result.
This is what I think is happening when the application loads:
- MainWindow loads
- MainWindow then see's the UserControl and notes it requires a property.
- Before WPF calls the UserControl constructor, it grabs the value of the property. It then initializes the component and automatically pushes the value to the UserControl's property
How can my UserControl use the Parents (MainWindow) property (Messages)