2016-06-08 1 views
0

ObservableStack을 Stackoverflow answer에서 복사했습니다. 내가 공용 속성관찰 가능한 스택 <T>이 푸시에서 작동하지 않습니다.

public ObservableStack<int> myStack; 

public MainPage() 
{ 
      myStack = new ObservableStack<int>(); 
      this.InitializeComponent(); 
      myButton.DataContext = myStack; 
} 
으로 뒤에 코드에서 스택을 정의

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 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에 버튼의 가시성을 바인딩하는 것을 시도하고있다

및 XAML은 다음과 같습니다.

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


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

다른 버튼 클릭 이벤트를 사용하여 int를 푸시하면 버튼이 여전히 보이지 않습니다. 무엇이 잘못 되었나요?

+0

나는 그것이'에 대한'PropertyChanged'을 제기 코드를 찾을 수 없습니다 "카운트"'항목 (또는 어떤 다른 일 경우) 추가되거나 제거 될 때. Stack에서 OnPropertyChanged를 호출 할 것인지 궁금합니다. 당신이 거기에 브레이크 포인트를 설정할 때, 당신은 그것을 치는가? '새로운 '것도 의심 스럽다. 나는이 혼란을 없애고 ObservableCollection에서 파생 된 아마 관찰 가능한 스택을 작성했습니다. 그 중 하나 또는 ObservableCollection에 대한 푸시 및 팝 확장 메서드를 작성하고 맥주에 나가. –

답변

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; 
} 

는 그리고 당신은 스택이 CountObservableStack 구현에서 변경된 것을 통지합니다.

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

대단히 감사합니다 – iamsharp

-2

기본 클래스 Stack이 "Count"를 바인딩 대상에 알리지 않기 때문입니다. OnCollectionChanged 메서드가 끝날 때

RaisePropertyChanged(new PropertyChangedEventArgs("Count")); 

내부에 다음을 추가하여 수동으로 알림을 보낼 수 있습니다.

+0

카운트는 변환기 내에서만 참조됩니다. 바인딩 로직은 Count가 'Count'에 있지 않기 때문에 Count가 변경되지 않도록주의합니다. –

+0

@Tyler가 맞습니다 – Natxo

1

ObservableStack은 콘텐츠가 변경되면 광고하지만 스택 자체가 변경되었음을 알리는 광고는 없습니다. 바인딩은 스택 자체에 있기 때문에이를 광고해야합니다.

DataContext 개체가 수정되었음을 알리는 방법은 분명치 않습니다. 필자는 DataContext 개체의 속성으로 만 작업을 수행했습니다. 당신은 실제로 단지 Count 속성을 사용하고 있기 때문에이 경우에, 당신은 당신의 대신 ObservableStack

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

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(); 
    } 
} 

에 컨버터를 변경하고 수 ObservableStack이 작업에 필요한 이벤트를 제기해야합니다.

RaisePropertyChanged 전화 번호를 Count에 포함시켜야한다고 filhit의 대답이 올 바릅니다. 나는 CollectionChanged가 또한 이것을 할 것이라고 생각했지만, 앞으로의 연구는 그렇지 않은 것으로 보인다.

관련 문제