2011-09-16 6 views
1

私は現在MVVMフレームワーク用のCaliburn.Microを実装しているSilverlightアプリケーションを使用しています。物事はうまくいっていますが、私はバインディングのいくつかの面白さに気付いています。私が持っているのは、アプリケーションのナビゲーションを処理するShellViewModelとShellViewです。 ShellViewModelには、アプリケーションのロードされたViewModelのリストがあります。 ShellViewModelは、Conductorから継承し、すべてのアクティブ化と非アクティブ化を処理できます。CaliburnエンティティデータバインディングFunniness

私はまた、ViewConductorから継承するBaseConductorViewModelというViewModel基本クラスの型も持っています。これは、基本的にマスター/ディテールのビューであるViewModelのためのものです。これらのBaseConductorViewModelsでは、BindableCollectionがItemsと呼ばれています。このアイデアは、このコレクションをListBoxや他のItemsControlにバインドすることです。

このViewModelの子を作成し、関連付けられたビューを表示すると、リストボックス(この場合))がActiveViewをShellViewModelレベルで変更したときにのみバインディングがリフレッシュされることがわかりました。したがって、アプリケーションが最初にロードされ、このビューがデフォルトのアクティブビューである場合、リストに何も表示されません(私はRiaサービスにこのリストのデータを取得しています)。しかし、ShellViewModel/ShellViewの別のViewModelをクリックしてから、それをクリックすると、リスト内の項目が表示されます。これは、リストに項目を追加したり削除したりする場合にも同様です。アクティブなビューを切り替えるまで、更新されません。これは私にとって非常に奇妙に思えます。私はそれを縛られる方法を見つけ出すことができません。アイテムを追加/削除しているときにもう1つ注意してください。 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 


} 
+0

ShellViewModelは導体から継承していますか?導体です.Collection.OneActive?可能であれば、ShellViewModelとBaseConductorViewModelのコードを投稿してください。 –

+0

私はこれらのオブジェクトのコードを投稿しました –

+0

ViewModelSelectedItemListはBaseConductorViewModelから継承していますか? –

答えて

0

わかりません問題はこれと関連があります。docs

物半導体のすべてのOOTB実装は 画面からそれを継承しているので、彼らはあまりにも彼らが行っているものは何でもアイテム のライフサイクルとそのライフサイクルのカスケードを有することを意味します。したがって、導体が非アクティブ化されている場合は、 のActiveItemも無効になります。 指揮官を閉じようとすると、 指揮者が行ったすべてのアイテムを閉じることができる場合にのみ、指揮官を閉じることができます。これは非常に強力な機能であることが判明しました。 これについて私が気づいたのは、 の開発者が頻繁に訪れます。 がアクティブでない指揮者のアイテムをアクティブにすると、指揮官が をアクティブにするまで、そのアイテムは実際にアクティブ化されません。これはあなたがそれについて考えるとき意味をなさないが、 は時には髪を引っ張ることがあります。

編集: 私もカップルの質問、私はあなたが何をしようとして見ると思う:

  1. あなたShellViewModelカタログ が活性化されると、 Conductor<IViewModel<V,M>>.Collection.OneActiveのですか?私はあなたがカタログに商品を追加したいと思うと思います。 それを有効にしてください。
  2. BaseConductorViewModelでは、導体から を継承しています。これは、 がバインドされているときに、そのビューへの参照を取得します。あなたが追加するViewプロパティが何のためのものなのか分かりません。
  3. CMは、選択したアイテムの設定を処理できます。そのため、ItemsControlを持っているマスター の詳細な状況では、CMは SelectedItemを設定し、そこから詳細を入力できます。
+0

Derekに感謝します。私はScreenから継承するベースViewModelでこれを試してみました。このシナリオでは、ShellViewModelがアクティブであったことを確認しました。私はBaseConductorViewModelでアクティビティの状態をチェックしましたが、ShellViewModelもこの場合アクティブです。 BaseConductorViewModelがアクティブであるかどうかを確認し、見つけたものを投稿するかどうかを確認します。 –

+0

マスター/ディテールについて言及しているので、View.Context添付のプロパティでHelloScreensの例を見たことがありますので、私はあなたのことを見ていきますか? –

+0

ありがとう、私はHelloScreensの例とView.Context添付されたプロパティを見てきました –