C# Caliburn.Micro BindableCollection未使用代码隐藏设置绑定来更新视图中的代码
我想使用Caliburn.Micro-MVVM创建一个WPF应用程序。其中一个视图应该可以很好地绘制为ViewModel获取的数据。在视图中,我想在代码隐藏中绘制。我使用标量依赖属性。那很好。我还可以使用BindableCollection中存储的数据(下面示例代码中的LocationList)。如果我向BindableCollection添加新元素,那么更新DependencyProperty将不起作用。这一定是个愚蠢的错误,但我看不出来。我创建了一个演示应用程序,尽可能省去了。这是一个标准的Caliburn.Micro设置。我不在这里显示引导程序、ShellView和ShellViewModel。它们是一般启动器配置 ViewModel如下所示:C# Caliburn.Micro BindableCollection未使用代码隐藏设置绑定来更新视图中的代码,c#,wpf,data-binding,caliburn.micro,inotifypropertychanged,C#,Wpf,Data Binding,Caliburn.micro,Inotifypropertychanged,我想使用Caliburn.Micro-MVVM创建一个WPF应用程序。其中一个视图应该可以很好地绘制为ViewModel获取的数据。在视图中,我想在代码隐藏中绘制。我使用标量依赖属性。那很好。我还可以使用BindableCollection中存储的数据(下面示例代码中的LocationList)。如果我向BindableCollection添加新元素,那么更新DependencyProperty将不起作用。这一定是个愚蠢的错误,但我看不出来。我创建了一个演示应用程序,尽可能省去了。这是一个标准的
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);
}
}
}
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
。在构造函数中,我为这个属性创建了一个绑定。在调试器中,我可以看到这实际上是可行的<如果此列表发生更改,则应调用code>OnLocationListChanged。当我在ViewModel的构造函数中创建LocationList
时,我看到这被调用,但是当我向LocationList
添加三个元素时,句柄不再被调用。因此,我认为问题在于如何处理INotifyChange
。为了更好地理解,我查阅了BindableCollection
类的源代码,发现Add
方法没有实现,所以我在ViewModel中更改了我的代码以使用AddRange
方法,只是为了确保这一点,但它没有帮助
我尝试了很多东西,但我完全不知道如何让它工作。我真的希望有人能帮我。基本上,所有这些都会导致我的应用程序再次调用OnRender来更新图形。这是我的第一个WPF绘图应用程序和我的第一个Caliburn.Micro应用程序,所以这一切对我来说仍然是新的
我的开发环境:Visual Studio 2019,社区版,.Net Core 3.1 C#8.0,Windows10。所有更新均使用最新补丁。您认为“如果此列表更改,则应调用OnLocationListChanged”的假设是错误的
依赖项属性的回调仅在属性本身设置为新值时调用,即将其分配给BindableCollection
的新实例时
在向集合中添加项或从集合中删除项时,不会调用它。有一个
CollectionChanged
事件,您可以处理该事件以响应添加或删除的单个项目。非常感谢您的帮助。它还不能解决我的问题,因为我还不知道如何在视图中实现CollectionChanged事件。BindableCollection调用此事件,因此这方面没有问题。适用于PropertyChanged DependencyProperty.Register帮助,但不适用于CollectionChanged。我可以注册到事件,这是有效的,但它似乎没有被调用。我将在生成的XAML代码中看到Microsoft是如何做到这一点的。我找到了窗口的示例代码,但没有找到UserControl的示例代码。任何想法或示例代码都是免费的welcome@RudolfJan:您可以将事件处理程序连接到OnLocationListChanged
回调中的事件。