首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Caliburn实体DataBinding趣味性

Caliburn实体DataBinding趣味性
EN

Stack Overflow用户
提问于 2011-09-17 06:02:55
回答 1查看 460关注 0票数 1

我有一个Silverlight应用程序,我目前正在为它的MVVM框架实现Caliburn.Micro。事情运行得很好,但我注意到一些绑定中的一些有趣之处。我拥有的是一个处理应用程序导航的ShellViewModel和ShellView。ShellViewModel具有为应用程序加载的ViewModels的列表。ShellViewModel继承自Conductor,因此它可以处理所有的激活和去激活。

我还有一个名为BaseConductorViewModel的ViewModel基类,它也继承自Conductor。这是针对ViewModel的,这些视图基本上是Master-Detail视图。对于这些项目,我有一个名为BaseConductorViewModels的BindableCollection。其思想是将此集合绑定到ListBox或其他ItemsControl。

当我创建这个ViewModel和一个相关视图的子级时,我注意到ListBox(在本例中)只在我在ShellViewModel级别更改ActiveItem时才刷新绑定。因此,当应用程序最初加载时,此视图是默认的活动视图,您将看不到列表中的任何内容(我将调用Ria服务来获取此列表的数据)。但是,如果我单击ShellViewModel/ShellView上的另一个ViewModel,然后单击back,它将显示列表中的项目。这也适用于向列表中添加项目或删除项目。它不会刷新,除非我切换活动视图。这对我来说似乎非常奇怪,我似乎找不到一种方法来绑定它,就像我想要的那样。还有一件事需要注意,当我添加/删除项目时,我调用了Refresh方法,目前我没有使用NotifyOfPropertyChange方法,尽管我以前也尝试过同样的结果。

有没有人知道这里可能发生了什么?或者有什么想法可以让我试着调试它?

提前谢谢你!

这是ShellViewModel

代码语言:javascript
复制
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

代码语言:javascript
复制
  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只是这个类的类型化版本

代码语言:javascript
复制
 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


}
EN

回答 1

Stack Overflow用户

发布于 2011-09-17 07:20:26

不确定你的问题是否与此有关,来自docs

由于IConductor的所有OOTB实现都继承自Screen,这意味着它们也有一个生命周期,并且生命周期级联到它们正在进行的任何项目。因此,如果一个conductor被停用,它的ActiveItem也将被停用。如果你试图关闭一个导体,它将只能关闭,如果它进行的所有项目都可以关闭。事实证明,这是一个非常强大的功能。关于这一点,我注意到有一个方面经常给开发人员带来麻烦。如果您激活了conductor中本身处于非活动状态的项目,则在conductor被激活之前,该项目实际上不会被激活。仔细想想,这是有道理的,但偶尔也会引起头发拉扯。

编辑:我想我知道你想做什么了,不过有几个问题:

  1. Your ShellViewModel is Conductor<IViewModel<V,M>>.Collection.OneActive,什么时候激活目录?我想你会想要将目录添加到项目中,然后激活它。带有BaseConductorViewModel
  2. ,它继承了从Screen继承的Conductor,当它被绑定时,它会获得对它的视图的引用。我不确定您添加的视图属性的用途。
  3. CM可以为您设置选定的项目。因此,对于具有ItemsControl的主详细情况,CM将设置SelectedItem,您可以从中填充详细信息。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7450848

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档