【问题标题】:ViewModel child doesn't refresh proper? binding in WPFViewModel 孩子没有正确刷新? 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;
    }

}

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

【问题讨论】:

    标签: wpf mvvm data-binding binding viewmodel


    【解决方案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 的分阶段创建。属性可以在基类中声明。派生类添加自己的属性。我们必须要求他们相互依赖。属性设置者根本无法做到这一点。这些困难在简单的任务中是不可见的。但最好立即习惯于正确行事。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    • 2023-03-30
    • 2016-06-04
    • 1970-01-01
    • 2023-03-29
    • 2011-10-22
    相关资源
    最近更新 更多