ViewModel 孩子没有正确刷新? WPF中的绑定

Posted

技术标签:

【中文标题】ViewModel 孩子没有正确刷新? WPF中的绑定【英文标题】:ViewModel child doesn't refresh proper? binding in WPF 【发布时间】:2021-07-25 00:51:36 【问题描述】:

我有一个视图,里面有另一个视图。我想为他们两个制作 ViewModel。但显然子视图中的绑定无法正常工作,或者我做了错误的绑定,也许。

我已经调试过,每次在父视图模型中选择不同的行时,都会重新创建子视图模型。 但 UI 不会刷新,尽管 UpdateSourceTrigger=PropertyChanged。

如果我在运行应用程序时在 XAML 中编辑绑定,那么它会被刷新(因为绑定可能会重新生成)。

我可以设置 UpdateSourceTrigger=Explicit,但我无法从任何 ViewModel 中调用 UpdateSource。

家长视图:

<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>

父视图模型:

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; 

儿童视图:

<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>

儿童视图模型:

public class AttachmentsViewModel : BaseViewModel

    public ObservableCollection<Attachment> Attachments  get; set; 

    public AttachmentsViewModel(ObservableCollection<Attachment> attachments)
    
        Attachments = attachments;
    


我做错了什么或者我理解错了什么概念?

【问题讨论】:

【参考方案1】:
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;
    

其他建议:向属性设置器添加额外的逻辑 - 不好。 当然,在 BaseViewModel 实现中,有机会以不同的方式设置属性之间的依赖关系。

【讨论】:

非常感谢。总结 - 我忘记让子 ViewModel 实例与 INotifyPropertyChanged 一起使用。现在正在为我工​​作。所以非常感谢。当我完成时,我会重新考虑这个 ViewModel 设计。我对 BaseViewModel 的实现非常简单,只有 INotifyPropertyChanged 的​​ 2 个方法。祝您有愉快的一天! У меня есть простая реализация。 Воспользуйтесь ею: BaseInpc @EldHasp,你能解释一下为什么向属性设置器添加额外的逻辑是不好的吗?我经常这样做,例如当我更改 ComboBox.SelectedItem 时,这会影响其他变量。我知道这不是最初的问题,但也很有趣。 这会混淆代码。让人难以阅读。如果出现错误,可能会出现一些错误。该属性已被分配一个值,并在视图中显示另一个值。最好编织已经在 WPF 实现中使用的基础。查看 DependecyProperty 是如何实现的。更改属性后,将调用处理更改值的方法。在我的课堂上,我做了一个简化的类比。 另外,在大型任务中,可以使用 ViewModel 的分阶段创建。属性可以在基类中声明。派生类添加自己的属性。我们必须要求他们相互依赖。属性设置者根本无法做到这一点。这些困难在简单的任务中是不可见的。但最好立即习惯于正确行事。

以上是关于ViewModel 孩子没有正确刷新? WPF中的绑定的主要内容,如果未能解决你的问题,请参考以下文章

WPF MVVM 从 ViewModel 触发事件的正确方法

WPF 将 UI 事件绑定到 ViewModel 中的命令

WPF 中的 MVVM - 如何提醒 ViewModel 模型中的变化......或者我应该吗?

我的 ViewModel 流程正确吗?如何将其发送回控制器并在控制器操作上刷新它?

模型更改时刷新 ViewModel 的所有属性的数据绑定的好方法

从 View 到 ViewModel 的 WPF 事件绑定?