I have one View that has another one inside. I want to make ViewModel for both of them. But apparently Binding in Child View is not working properly or I have done wrong binding, perhaps.
I have debugged that Child ViewModel is recreated every time I have selected different row in Parent ViewModel. But UI, doesn't refresh, despite UpdateSourceTrigger=PropertyChanged.
If I edit Binding in XAML while running app then it gets refreshed (as Binding probably is regenerated).
I could set UpdateSourceTrigger=Explicit, but I can't call UpdateSource from none of ViewModels.
PARENT VIEW:
<UserControl ... DataContext="{Binding ProjectsViewModel, Source={StaticResource ViewModelLocator}}">
<Grid>
<poc:AdvancedListView ItemsSource="{Binding Projects}" SelectedObject="{Binding SelectedProject, Mode=TwoWay}"/>
...
<ScrollViewer>
<StackPanel Orientation="Vertical">
...
<poc:Section SectionName="ATTACHMENTS">
<poc:AttachmentsControl DataContext="{Binding AttachmentsViewModel, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" /> // THIS IS BINDING BETWEEN VM
</poc:Section>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>
PARENT VIEWMODEL:
public class ProjectsViewModel : BaseViewModel
{
public ProjectsViewModel(ObservableCollection<Project> projects)
{
this.Projects = projects;
}
public ObservableCollection<Project> Projects { get; }
private Project selectedProject;
public Project SelectedProject
{
get { return selectedProject; }
set
{
SetPropertyAndNotify(ref selectedProject, value);
AttachmentsViewModel = new AttachmentsViewModel(selectedProject.Attachments); // THIS IS CREATION OF CHILD VM
}
}
public AttachmentsViewModel AttachmentsViewModel { get; set; }
}
CHILD VIEW:
<UserControl ... x:Name="attachmentControl">
<Grid x:Name="mainGrid">
...
<ListView x:Name="attachmentsListView" ItemsSource="{Binding Attachments, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" SelectionMode="Single"> // THIS IS BINDING TO LIST THAT IS NOT WORKING
<ListView.View>
<GridView>
...
</GridView>
</ListView.View>
</ListView>
</Grid>
</UserControl>
CHILD VIEWMODEL:
public class AttachmentsViewModel : BaseViewModel
{
public ObservableCollection<Attachment> Attachments { get; set; }
public AttachmentsViewModel(ObservableCollection<Attachment> attachments)
{
Attachments = attachments;
}
}
What I do wrong or what concept I have understood wrong?
public class ProjectsViewModel : BaseViewModel
{
public ProjectsViewModel(ObservableCollection<Project> projects)
{
this.Projects = projects;
}
public ObservableCollection<Project> Projects { get; }
private Project selectedProject;
public Project SelectedProject
{
get { return selectedProject; }
set
{
SetPropertyAndNotify(ref selectedProject, value);
// THIS IS CREATION OF CHILD VM
AttachmentsViewModel = new AttachmentsViewModel(selectedProject.Attachments);
}
}
private AttachmentsViewModel _attachmentsViewModel;
public AttachmentsViewModel AttachmentsViewModel
{
get => _attachmentsViewModel;
set => SetPropertyAndNotify(_attachmentsViewModel, value);
}
}
public class AttachmentsViewModel : BaseViewModel
{
// This should be a Read Only property
public ObservableCollection<Attachment> Attachments { get; /* set; */}
public AttachmentsViewModel(ObservableCollection<Attachment> attachments)
{
Attachments = attachments;
}
}
Additional recommendation: Adding extra logic to the property setter - is bad. Surely in the BaseViewModel implementation there is an opportunity to set the dependence of properties on each other in a different way.