2016-06-08 35 views
0

我從Stackoverflow answer複製了ObservableStack。Observable Stack <T>無法正常工作

public class ObservableStack<T> : Stack<T>, INotifyCollectionChanged, INotifyPropertyChanged 
    { 
     public ObservableStack() 
     { 
     } 

     public ObservableStack(IEnumerable<T> collection) 
     { 
      foreach (var item in collection) 
       base.Push(item); 
     } 

     public ObservableStack(List<T> list) 
     { 
      foreach (var item in list) 
       base.Push(item); 
     } 


     public new virtual void Clear() 
     { 
      base.Clear(); 
      this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
     } 

     public new virtual T Pop() 
     { 
      var item = base.Pop(); 
      this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); 
      return item; 
     } 

     public new virtual void Push(T item) 
     { 
      base.Push(item); 
      this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); 
     } 


     public virtual event NotifyCollectionChangedEventHandler CollectionChanged; 


     protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
     { 
      this.RaiseCollectionChanged(e); 
     } 

     protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
     { 
      this.RaisePropertyChanged(e); 
     } 


     protected virtual event PropertyChangedEventHandler PropertyChanged; 


     private void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e) 
     { 
      if (this.CollectionChanged != null) 
       this.CollectionChanged(this, e); 
     } 

     private void RaisePropertyChanged(PropertyChangedEventArgs e) 
     { 
      if (this.PropertyChanged != null) 
       this.PropertyChanged(this, e); 
     } 


     event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged 
     { 
      add { this.PropertyChanged += value; } 
      remove { this.PropertyChanged -= value; } 
     } 
    } 

,現在我嘗試使用下面的轉換器類綁定按鈕來Stack.Count能見度:

public class StackToVisibilityConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, string language) 
     { 
      var collection = (Stack<int>)value; 
      return collection.Count > 0 ? Visibility.Visible : Visibility.Collapsed; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, string language) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

我在代碼中定義的堆後面爲公共財產

public ObservableStack<int> myStack; 

public MainPage() 
{ 
      myStack = new ObservableStack<int>(); 
      this.InitializeComponent(); 
      myButton.DataContext = myStack; 
} 

和XAML如下:

<Page.Resources> 
     <Converters:StackToVisibilityConverter x:Key="StackToVisibilityConverter"/> 
    </Page.Resources> 


<Button x:Name="myButton" Content="Test Button" Visibility="{Binding Converter={StaticResource StackToVisibilityConverter}}"/> 

現在,當我使用另一個按鈕單擊事件來推動一個int時,該按鈕仍然是不可見的,我做錯了什麼?

+0

當添加或刪除項目(或其他任何事情發生時)時,我無法找到爲「Count」引發'PropertyChanged'的代碼。我想知道Stack上的任何東西是否會打電話給你的OnPropertyChanged;當你在那裏設置斷點時,你有沒有打過它? 「新」東西也值得懷疑。我會清理這個混亂,並寫我自己的可觀察堆棧,可能派生自ObservableCollection。無論是那個,還是我只爲ObservableCollection編寫Push和Pop擴展方法,然後出去喝啤酒。 –

回答

1

堆棧本身不會更改爲另一個堆棧,因此在彈出或推送時不會重新評估綁定。

您應該綁定到Count屬性,並更改轉換器以將計數轉換爲可見性。

<Button x:Name="myButton" Content="Test Button" Visibility="{Binding Count, Converter={StaticResource GreaterThanEqualIntToVisibilityConverter}}"/> 

轉換器:

public object Convert(object value, Type targetType, object parameter, string language) 
{ 
    var count = (int)value; 
    return count > 0 ? Visibility.Visible : Visibility.Collapsed; 
} 

你想堆通知,在ObservableStack實現改變Count

protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
{ 
    this.RaiseCollectionChanged(e); 
    RaisePropertyChanged(new PropertyChangedEventArgs("Count")); 
} 
+0

非常感謝你 – iamsharp

-2

這是因爲基類Stack不會將「計數」通知給綁定目標。您可以通過添加以下內容手動通知:

RaisePropertyChanged(new PropertyChangedEventArgs("Count")); 

裏面的OnCollectionChanged方法結束。

+0

計數僅在轉換器內引用。綁定邏輯不會在乎計數改變,因爲綁定不在'計數' –

+0

@泰勒是正確的 – Natxo

1

ObservableStack當內容發生變化時發佈廣告,但您沒有任何廣告宣稱堆棧本身已更改。由於你的綁定本身就是堆棧,所以你需要做廣告。

不幸的是,我不完全確定如何通告DataContext對象已被修改;我只用DataContext對象的屬性來完成它。在這種情況下,因爲你實際上只使用Count屬性,則可以將轉換器改爲

public class StackToVisibilityConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, string language) 
    { 
     var count = (int)value; 
     return count > 0 ? Visibility.Visible : Visibility.Collapsed; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, string language) 
    { 
     throw new NotImplementedException(); 
    } 
} 

,然後更新您的綁定來綁定到Count代替ObservableStack

<Button x:Name="myButton" Content="Test Button" Visibility="{Binding Path=Count, Converter={StaticResource StackToVisibilityConverter}}"/> 

ObservableStack應該正在籌備必要的事件以便使其工作

filhit的答案很可能是正確的,你將不得不包括CountRaisePropertyChanged來電。我認爲CollectionChanged也會這樣做,但進一步的研究似乎表明不是。