Я хочу создать приложение WPF, используя Caliburn.Micro MVVM. Один из видов должен хорошо рисовать данные, полученные для ViewModel. В представлении я хочу сделать рисунок в коде позади. Я использую скалярные свойства зависимости. Это отлично работает. Я также могу использовать данные, хранящиеся в BindableCollection (LocationList в примере кода ниже). Не работает обновление DependencyProperty, если я добавляю новые элементы в BindableCollection. Должно быть, это глупая ошибка, но я ее не вижу. Я создал демо-приложение, оставив как можно больше. Это стандартная настройка 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. Все обновлено с последними исправлениями.