2012-08-28 335 views
2

我在頁面上有一個選項卡控件;它的項目被綁定回我的ViewModel,它還暴露了一個ActiveTabItemIndex,它綁定到我的xaml中的SelectedIndex屬性,並實現INotifyPropertyChanged,以便我的TabControl知道何時更新。綁定到TabControl SelectedIndex

這是(我明白)MVVM正確的方式來做事情,並適當地工作99%。

class MainWindowViewModel : BaseViewModel, INotifyPropertyChanged 
{ 
    ObservableCollection<TabItemViewModel> _TabItems; 
    int _ActiveTabItemIndex; 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChanged(string name) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(name)); 
    } 

    void _TabItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) 
      _ActiveTabItemIndex = _TabItems.IndexOf((TabItemViewModel)e.NewItems[0]); 
     RaisePropertyChanged("ActiveTabItemIndex"); 
    } 

    public ObservableCollection<TabItemViewModel> TabItems 
    { 
     get 
     { 
      if (_TabItems == null) 
      { 
       _TabItems = new ObservableCollection<TabItemViewModel>(); 
       _TabItems.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_TabItems_CollectionChanged); 
      } 
      return _TabItems; 
     } 
    } 

    public int ActiveTabItemIndex 
    { 
     get 
     { 
      return _ActiveTabItemIndex; 
     } 
     set 
     { 
      _ActiveTabItemIndex = value; 
     } 
    } 
} 

這樣,我讓我的TabItems集合中的任何操作都反映在TabControl的,當我添加一個新的項目,則會自動選擇。這是一種享受;然而,加入,第一項爲空標籤控件時,它看起來像這樣:顯示

Tab contents displayed but tab not selected

的標籤內容,但沒有選擇選項卡。我需要手動點擊標籤得到它看的權利:

Tab contents displayed and tab selected

就好像有某種標籤的繪圖和對其內容的圖畫之間的脫節。我知道綁定正在工作,因爲隨後的選項卡處理正確,並且如果我完全刪除綁定,那麼在手動選擇選項卡之前,第一頁不顯示其內容。如果有人看到了這一點,或可以擺脫一些光,這將非常感激!謝謝大家:)

+0

也許和[this issue]一樣的修復(http://stackoverflow.com/questions/4222535/tabcontrol-selectedindex-changed-event-getting-fired-c-sharp)(以winforms形式)適用。 –

回答

2

只在籌備者提高你的財產變化事件;你可以把它看成允許屬性本身來決定什麼是「改變」的意思,並推而廣之,給它的控制權,當事件被觸發(也能夠做你所期望的):

public int ActiveTabItemIndex 
{ 
    get{ return _ActiveTabItemIndex; } 
    set 
    { 
     if(_ActiveTabItemIndex != value) 
     { 
      _ActiveTabItemIndex = value; 
      RaisePropertyChanged("ActiveTabItemIndex"); 
     } 
    } 
} 

只是改變

_ActiveTabItemIndex = _TabItems.IndexOf(...); 

ActiveTabItemIndex = _TabItems.IndexOf(...); 

和_TabItems_CollectionChanged

刪除RaisePropertyChanged通話

有時你需要在財產的設置者之外提高財產變更通知,但這是一個複雜得多的日子:)

另外,INotifyPropertyChanged應該在你的BaseViewModel上實現。看看絕對精彩的MVVM Light Toolkit - 它擁有所有的代碼,否則你必須在每個使用MVVM的項目中複製。

+0

巨大!非常感謝humanitas--這正是我需要的;並且if(_ActiveTabItemIndex!= value)部分被證明是至關重要的。另外,這是關於將INotifyPropertyChanged實現放入baseview模型的好建議;那就是我把它移到現在的地方! –