I have ListBox with list of notes (NoteList) that represented by the Note Model (subject, text, id):
<ListBox x:Name="NotesListBox" ItemsSource="{Binding NoteList}">
<ListBox.ItemTemplate>
<DataTemplate>
<UserControls:NoteHeadControl/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ListItem I created in separate UserControl (NoteHeadControl). Was decided to pass Id by Tag property. I`m not sure that it is the best way of doing this, but I don't know how to do it other way.
<Button Name="OpenButton" Tag="{Binding id}">
<DockPanel>
<Label Content="{Binding subject}"/>
<Button Command="{Binding DeleteNoteCommand}" Name="DeleteNoteButton" Content="Delete"/>
</DockPanel>
</Button>
For NoteHeadControl I created separate ViewModel (NoteHeadControlViewModel ) where my commands and properties should be. For example, I want to create a DELETE button on note to delete it from my database. For this Id parameter is required in NoteHeadControlViewModel.
The problem happens when I try to pass Id data from View to ViewModel:
public NoteHeadControl()
{
InitializeComponent();
NoteHeadControlViewModel noteHeadControlViewModel = new NoteHeadControlViewModel((int)this.OpenButton.Tag);
DataContext = noteHeadControlViewModel;
}
It seems that UserControl is not completely initialized at the moment when (int)this.OpenButton.Tag
is run and OpenButton is just not found (null).
The question is, how can I pass data (Id in my case) from Window -> UserControl -> UserControl`s ViewModel ?
I tried to set Tag property not in the Button, but in UserControl controller. UserControl is initialized, but the property is still null.
This task has so many steps and so many of my decision looks kind of strange (I`m still learning and most of them I found here or on other resources) so I don't know where I have done the biggest mistake or what I don't know to resolve the issue by myself.
For NoteHeadControl I created separate ViewModel (NoteHeadControlViewModel ) where my commands and properties should be.
This is wrong. The UserControl
should not have its own view model. It should inherit the DataContext
from the parent element.
What you can do is to add an ICommand
dependency property to the NoteHeadControl
and bind this one to a command of the parent view model that should be responsible for deleting the item:
<UserControls:NoteHeadControl DeleteCommand="{Binding DataContext.DeleteNoteCommand,
RelativeSource={RelativeSource AncestorType=ListBox}}" CommandParameter="{Binding}" />
In the control, you then bind the Command
property of the Button
to the dependency property:
<Button Command="{Binding DeleteCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
Content="Delete"/>
But don't break the DataContext
inheritance by explicitly setting the DataContext
of the control like this:
NoteHeadControlViewModel noteHeadControlViewModel = new NoteHeadControlViewModel((int)this.OpenButton.Tag);
DataContext = noteHeadControlViewModel;