У меня есть приложение Silverlight, в котором я сейчас работаю, которое реализует Caliburn.Micro для своей инфраструктуры MVVM.Все работает хорошо, но я замечаю некоторую забавность в некоторых связывании.У меня есть ShellViewModel и ShellView, которые обрабатывают навигацию для приложения.ShellViewModel имеет список загруженных ViewModel для приложения.ShellViewModel наследуется от Conductor, так что он может обрабатывать все активации и деактивации.
У меня также есть тип базового класса ViewModel, называемый BaseConductorViewModel, который также наследуется от Conductor.Это для ViewModel, которые в основном являются представлениями Master-Detail.Для этих BaseConductorViewModels у меня есть BindableCollection с именем Items.Идея заключается в том, чтобы связать эту коллекцию с ListBox или другим ItemsControl.
Когда я создаю дочерний элемент этой ViewModel и связанного с ним представления, я заметил, что ListBox (в данном случае) обновляет привязку только при измененииActiveItem на уровне ShellViewModel.Поэтому, когда приложение изначально загружается и это представление является активным представлением по умолчанию, вы ничего не увидите в списке (я звоню в службу Ria, чтобы получить данные для этого списка).Но если я нажму на другую ViewModel в ShellViewModel / ShellView, а затем нажму назад, она покажет элементы в списке.Это также следует для добавления элементов в список или их удаления.Он не обновится, пока я не переключу активные виды.Это кажется мне очень странным, и я не могу придумать способ связать его, как я бы хотел.Еще одна вещь, которую нужно отметить, когда я добавляю / удаляю элементы;Я вызываю метод Refresh, в настоящее время я не использую метод NotifyOfPropertyChange, хотя я пытался сделать это ранее с тем же результатом.
У кого-нибудь есть идеи о том, что здесь может происходить?Или какие-нибудь идеи о том, как я могу попытаться отладить это?
Заранее спасибо!
Вот ShellViewModel
public abstract class ShellViewModel<V,M>:Conductor<IViewModel<V, M>>.Collection.OneActive, IViewModelCatalogShell<V,M>
where V:IView
where M:IModel
{
#region Properties/Members
public ViewModelSelectedItemList<V, M> Catalog { get; set; }
#endregion
#region Constructors
public ShellViewModel()
{
Catalog = new ViewModelSelectedItemList<V, M>();
}
#endregion
}
А вот BaseConductorViewModel
public abstract class BaseConductorViewModel<T,V,M>:Conductor<T>, IViewModel<V, M>
where V:IView
where M:IModel
{
#region Properties/Members
protected Guid _id=Guid.Empty;
public Guid Id
{
get{return _id;}
set
{
_id =value;
NotifyOfPropertyChange("Id");
}
}
protected string _name=string.Empty;
public string Name
{
get { return _name; }
set
{
_name = value;
NotifyOfPropertyChange("Name");
}
}
public string TypeName
{
get
{
return this.GetType().FullName;
}
}
protected string _description = string.Empty;
public string Description
{
get { return _description; }
protected set
{
_description = value;
NotifyOfPropertyChange(() => Description);
}
}
protected V _view;
public V View
{
get { return _view; }
set
{
_view = value;
NotifyOfPropertyChange("View");
}
}
protected M _model;
public M Model
{
get { return _model; }
set
{
_model = value;
NotifyOfPropertyChange("Model");
}
}
protected SelectedItemList<T> _items;
public SelectedItemList<T> Items
{
get { return _items; }
set
{
_items = value;
NotifyOfPropertyChange(() => Items);
}
}
protected Guid _lastModifiedBy = Guid.Empty;
public Guid LastModifiedBy
{
get { return _lastModifiedBy; }
set
{
_lastModifiedBy = value;
NotifyOfPropertyChange("LastModifiedBy");
}
}
protected DateTime _lastModifiedOn = DateTime.Today;
public DateTime LastModifiedOn
{
get { return _lastModifiedOn; }
set
{
_lastModifiedOn = value;
NotifyOfPropertyChange("LastModifiedOn");
}
}
protected string _imageSource = string.Empty;
public string ImageSource
{
get { return _imageSource; }
protected set
{
_imageSource = value;
NotifyOfPropertyChange("ImageSource");
}
}
#endregion
#region Constructors
public BaseConductorViewModel()
{
_items = new SelectedItemList<T>();
Items.SelectItemChanged += new SelectedItemChangedEvent(Items_SelectItemChanged);
Items.SelectedIndexChanged += new SelectedIndexChangedEvent(Items_SelectedIndexChanged);
LoadData();
}
public BaseConductorViewModel(V view, M model)
:this()
{
_items = new SelectedItemList<T>();
View = view;
Model = model;
Items.SelectItemChanged += new SelectedItemChangedEvent(Items_SelectItemChanged);
Items.SelectedIndexChanged += new SelectedIndexChangedEvent(Items_SelectedIndexChanged);
LoadData();
}
#endregion
#region Methods
public abstract void LoadData();
#endregion
#region Event Handlers
private void Items_SelectItemChanged()
{
ChangeActiveItem(Items.SelectedItem, true);
OnActiveItemChanged();
}
private void Items_SelectedIndexChanged(int index)
{
ChangeActiveItem(Items.SelectedItem, true);
OnActiveItemChanged();
}
#endregion
}
ViewModelSelectedItemList - это просто типизированная версия этого класса
public class SelectedItemList<T>:IObservableCollection<T>
{
#region Properties/Members
protected BindableCollection<T> _items = new BindableCollection<T>();
protected bool _isReadOnly = false;
protected bool _isNotifying = true;
public bool IsNotifying
{
get
{
return _isNotifying;
}
set
{
_isNotifying = value;
}
}
public int Count
{
get { return _items.Count; }
}
protected int _selectedIndex = -1;
public int SelectedIndex
{
get { return _selectedIndex; }
set
{
_selectedIndex = value;
NotifyOfPropertyChange("SelectedIndex");
FireSelectedIndexChangedEvent(_selectedIndex);
}
}
public T SelectedItem
{
get
{ return _items[_selectedIndex]; }
set
{
_selectedIndex = _items.IndexOf(value);
NotifyOfPropertyChange("SelectedItem");
FireSelectedItemChangedEvent();
}
}
#endregion
#region Events
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged;
public event SelectedIndexChangedEvent SelectedIndexChanged;
public event SelectedItemChangedEvent SelectItemChanged;
#endregion
#region Constructors
#endregion
#region Methods
public void AddRange(System.Collections.Generic.IEnumerable<T> items)
{
if (!_isReadOnly)
{
foreach (T item in items)
{
_items.Add(item);
}
if (_isNotifying)
{
NotifyOfPropertyChange("Count");
}
}
}
public void RemoveRange(System.Collections.Generic.IEnumerable<T> items)
{
if (!_isReadOnly)
{
foreach (T item in items)
{
_items.Remove(item);
}
if (_isNotifying)
{
NotifyOfPropertyChange("Count");
}
}
}
public int IndexOf(T item)
{
return _items.IndexOf(item);
}
public void Insert(int index, T item)
{
if (!_isReadOnly)
{
_items.Insert(index, item);
if (_isNotifying)
{
NotifyOfPropertyChange("Count");
}
}
}
public void RemoveAt(int index)
{
if (!_isReadOnly)
{
_items.RemoveAt(index);
if (_isNotifying)
{
NotifyOfPropertyChange("Count");
}
}
}
public T this[int index]
{
get
{
return _items[index];
}
set
{
_items[index] = value;
}
}
public void Add(T item)
{
if (!_isReadOnly)
{
_items.Add(item);
if (_isNotifying)
{
NotifyOfPropertyChange("Count");
_items.Refresh();
}
if (_items.Count == 1)
{
SelectedIndex = 0;
}
}
}
public bool Remove(T item)
{
if (!_isReadOnly)
{
if (_isNotifying)
{
NotifyOfPropertyChange("Count");
}
return _items.Remove(item);
}
else
{
return false;
}
}
public void Clear()
{
_items.Clear();
}
public bool Contains(T item)
{
return _items.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
if (!_isReadOnly)
{
_items.CopyTo(array, arrayIndex);
if (_isNotifying)
{
NotifyOfPropertyChange("Count");
}
}
}
public bool IsReadOnly
{
get { return _isReadOnly; }
}
public void Lock()
{
_isReadOnly = true;
}
public void Unlock()
{
_isReadOnly = false;
}
public System.Collections.Generic.IEnumerator<T> GetEnumerator()
{
return _items.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _items.GetEnumerator();
}
public void NotifyOfPropertyChange(string propertyName)
{
FirePropertyChangedEvent(propertyName);
}
public void Refresh()
{
_items.Refresh();
}
#region Helper Methods
protected void FirePropertyChangedEvent(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
protected void FireCollectionChangedEvent(NotifyCollectionChangedAction action)
{
if (CollectionChanged != null)
{
CollectionChanged(this, new System.Collections.Specialized.NotifyCollectionChangedEventArgs(action));
}
}
protected void FireSelectedIndexChangedEvent(int index)
{
if (SelectedIndexChanged != null)
{
SelectedIndexChanged(index);
}
}
protected void FireSelectedItemChangedEvent()
{
if (SelectItemChanged != null)
{
SelectItemChanged();
}
}
#endregion
#endregion
}