我有一个我目前正在使用的 Silverlight 应用程序,它为其 MVVM 框架实现了 Caliburn.Micro。一切正常,但我注意到一些绑定中的一些有趣之处。我拥有的是处理应用程序导航的 ShellViewModel 和 ShellView。ShellViewModel 有一个为应用程序加载的 ViewModel 的列表。ShellViewModel 继承自 Conductor,因此它可以处理所有的激活和停用。
我还有一种 ViewModel 基类,称为 BaseConductorViewModel,它也继承自 Conductor。这适用于基本上是 Master-Detail 视图的 ViewModel。对于这些 BaseConductorViewModels,我有一个名为 Items 的 BindableCollection。想法是将这个集合绑定到 ListBox 或其他 ItemsControl。
当我创建此 ViewModel 的子项和关联的 View 时,我注意到 ListBox(在这种情况下)仅在我更改 ShellViewModel 级别的 ActiveItem 时才刷新绑定。因此,当应用程序最初加载并且此视图是默认的活动视图时,您不会在列表中看到任何内容(我正在调用 Ria 服务来获取此列表的数据)。但是,如果我单击 ShellViewModel/ShellView 上的另一个 ViewModel,然后单击返回,它将显示列表中的项目。这也适用于将项目添加到列表或删除它们。除非我切换活动视图,否则它不会刷新。这对我来说似乎很奇怪,我似乎无法像我想的那样想办法让它绑定。还有一件事要注意,当我添加/删除项目时;我调用 Refresh 方法,
有人对这里可能发生的事情有任何想法吗?或者关于我如何尝试调试它的任何想法?
先感谢您!
这是 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
}