Caliburn.Micro BindableCollection在View代码中没有更新,使用后面的代码来设置绑定。

问题描述 投票:0回答:1

我想使用Caliburn.Micro MVVM创建一个WPF应用程序。其中的一个View应该对ViewModel获得的数据进行漂亮的绘制。在View中,我想在后面的代码中进行绘制。我使用标量依赖属性。这很好用。我也可以使用存储在BindableCollection中的数据(下面例子代码中的LocationList)。不起作用的是,如果我向BindableCollection中添加新元素,就会更新DependencyProperty。这一定是一个愚蠢的错误,但我没有看到它。我创建了一个演示应用程序,尽可能地省略了很多内容。这是一个标准的Caliburn.Micro设置。我没有在这里显示Bootstrapper、ShellView和ShellViewModel。它们是一般的入门配置。

ViewModel是这样的。

    using Caliburn.Micro;
    using System.Collections.Generic;

    namespace BindingCodeBehind.ViewModels
        {
        public class DemoViewModel : Screen
            {
            private BindableCollection<string> _locationList;
            public BindableCollection<string> LocationList
                {
                get { return _locationList; }
                set
                    {
                    _locationList = value; 
                    NotifyOfPropertyChange(()=>LocationList);
                    }
                }

            public DemoViewModel()
                {
                LocationList = new BindableCollection<string>();
                }

            protected override void OnViewLoaded(object view)
                {
                base.OnViewLoaded(view);
                for (int i = 0; i < 3; i++)
                    {
                    // BindableCollection supports AddRange, but not Add. 
                    LocationList.AddRange( new List<string>{$"Test nr {i}"});
                    // LocationList.Add($"Test nr {i}");
                    }
                NotifyOfPropertyChange(()=>LocationList.Count);
                }
            }
        }

LocationList 在构造函数中被初始化。我在 OnViewLoaded 事件处理程序。

视图的XAML代码没有什么特别的,只是一个脚手架式的 UserControl,什么也没加。后面的代码是这样的。

using Caliburn.Micro;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;

namespace BindingCodeBehind.Views
    {
    public partial class DemoView : UserControl
        {
        public BindableCollection<string> LocationList
            {
            get { return (BindableCollection<string>) GetValue(LocationListProperty); }
            set { SetValue(LocationListProperty, value);}
            }

        public static readonly DependencyProperty LocationListProperty =
            DependencyProperty.Register("LocationList", 
                typeof(BindableCollection<string>), 
                typeof(DemoView),
                new FrameworkPropertyMetadata(null, 
                                            FrameworkPropertyMetadataOptions.AffectsRender,
                                            new PropertyChangedCallback(OnLocationListChanged)));

        public DemoView()
            {
            InitializeComponent();
            var myBinding = new Binding
                {
                Mode = BindingMode.TwoWay,
                Path = new PropertyPath("LocationList"),
                NotifyOnSourceUpdated = true
                };
            BindingOperations.SetBinding(this, LocationListProperty, myBinding);
            }

        protected override void OnRender(DrawingContext drawingContext)
            {
            // Data from LocationLst should be used in drawing 
            }

        private static void OnLocationListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
            // I assume this called if LocationList changes
            }
        }
    }

在代码中,有一个依赖属性 LocationList 被创建。在构造函数中,我为这个属性创建了一个绑定。在调试器中,我看到这实际上是有效的。OnLocationListChanged 如果这个列表发生变化,应该调用这个函数。我看到当我创建 LocationList 的构造函数中,但当我在ViewModel中添加三个元素时,句柄没有被再次调用。LocationList. 因此,我认为问题出在了对 INotifyChange. 为了更好的理解,我查了一下源代码的 BindableCollection 课堂上,看到 Add 方法没有实现,所以我在ViewModel中修改了我的代码,使用了 AddRange 方法,只是为了确定,但它没有帮助。

我试了很多办法,但是我完全没有办法让这个事情成功。我真的希望有人能帮助我。基本上,所有这些都应该导致我的应用程序的调用。OnRender 再次更新绘图。这是我的第一个WPF绘图应用,也是我的第一个Caliburn.Micro应用,所以这一切对我来说还是很陌生的。

我的开发环境。Visual Studio 2019, 社区版, .Net Core 3.1 C# 8.0, Windows10. 都是用最新的补丁更新的。

c# wpf data-binding caliburn.micro inotifypropertychanged
1个回答
1
投票

你的假设是"如果这个列表发生变化,应该调用OnLocationListChanged。"是错误的。

依赖属性的回调只有在属性本身被设置为新的值时才会被调用,也就是当你将它分配给一个新的 BindableCollection<string>.

当你在收藏中添加或删除物品时,它不会被调用。有一个 CollectionChanged 事件,你可以处理到响应个别项目被添加或删除。

© www.soinside.com 2019 - 2024. All rights reserved.