ViewModel child 没有正确刷新?在 WPF 中绑定
ViewModel child doesn't refresh proper? binding in WPF
我有一个视图,里面有另一个视图。我想为他们两个制作 ViewModel。但显然 Child View 中的 Binding 无法正常工作,或者我做错了绑定,也许。
我已经调试过,每次我在 Parent ViewModel 中选择不同的行时,都会重新创建 Child ViewModel。
但是 UI,不刷新,尽管 UpdateSourceTrigger=PropertyChanged。
如果我在 XAML 中编辑 Binding 而 运行 应用程序则会刷新(因为 Binding 可能会重新生成)。
我可以设置 UpdateSourceTrigger=Explicit,但我无法从 ViewModels 的 none 调用 UpdateSource。
PARENT 视图:
<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 视图模型:
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 视图:
<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 视图模型:
public class AttachmentsViewModel : BaseViewModel
{
public ObservableCollection<Attachment> Attachments { get; set; }
public AttachmentsViewModel(ObservableCollection<Attachment> attachments)
{
Attachments = attachments;
}
}
我做错了什么或者我理解错了什么概念?
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;
}
}
附加建议:向 属性 setter 添加额外的逻辑是不好的。
当然,在 BaseViewModel 实现中,有机会以不同的方式设置属性之间的依赖关系。
我有一个视图,里面有另一个视图。我想为他们两个制作 ViewModel。但显然 Child View 中的 Binding 无法正常工作,或者我做错了绑定,也许。
我已经调试过,每次我在 Parent ViewModel 中选择不同的行时,都会重新创建 Child ViewModel。 但是 UI,不刷新,尽管 UpdateSourceTrigger=PropertyChanged。
如果我在 XAML 中编辑 Binding 而 运行 应用程序则会刷新(因为 Binding 可能会重新生成)。
我可以设置 UpdateSourceTrigger=Explicit,但我无法从 ViewModels 的 none 调用 UpdateSource。
PARENT 视图:
<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 视图模型:
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 视图:
<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 视图模型:
public class AttachmentsViewModel : BaseViewModel
{
public ObservableCollection<Attachment> Attachments { get; set; }
public AttachmentsViewModel(ObservableCollection<Attachment> attachments)
{
Attachments = attachments;
}
}
我做错了什么或者我理解错了什么概念?
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;
}
}
附加建议:向 属性 setter 添加额外的逻辑是不好的。 当然,在 BaseViewModel 实现中,有机会以不同的方式设置属性之间的依赖关系。