Observable Stack<T> 无法处理推送
Observable Stack<T> is not working on push
我从 Whosebug answer 复制了 ObservableStack。
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; }
}
}
现在我正尝试使用以下转换器 class:
将按钮的可见性绑定到 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 属性
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 时,该按钮仍然不可见,我做错了什么?
那是因为基础 class 堆栈没有通知 "Count" 绑定目标。您可以通过添加手动通知:
RaisePropertyChanged(new PropertyChangedEventArgs("Count"));
在 OnCollectionChanged 方法的末尾。
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 的回答很可能是正确的,您必须包含 RaisePropertyChanged
对 Count
的调用。我认为 CollectionChanged 也会这样做,但进一步的研究似乎表明不会。
堆栈本身不会更改为另一个堆栈,因此在弹出或推送时不会重新评估绑定。
您应该改为绑定到 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;
}
并且您希望堆栈通知 Count
在 ObservableStack
实现中发生了更改。
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
this.RaiseCollectionChanged(e);
RaisePropertyChanged(new PropertyChangedEventArgs("Count"));
}
我从 Whosebug answer 复制了 ObservableStack。
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; }
}
}
现在我正尝试使用以下转换器 class:
将按钮的可见性绑定到 Stack.Countpublic 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 属性
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 时,该按钮仍然不可见,我做错了什么?
那是因为基础 class 堆栈没有通知 "Count" 绑定目标。您可以通过添加手动通知:
RaisePropertyChanged(new PropertyChangedEventArgs("Count"));
在 OnCollectionChanged 方法的末尾。
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 的回答很可能是正确的,您必须包含 RaisePropertyChanged
对 Count
的调用。我认为 CollectionChanged 也会这样做,但进一步的研究似乎表明不会。
堆栈本身不会更改为另一个堆栈,因此在弹出或推送时不会重新评估绑定。
您应该改为绑定到 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;
}
并且您希望堆栈通知 Count
在 ObservableStack
实现中发生了更改。
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
this.RaiseCollectionChanged(e);
RaisePropertyChanged(new PropertyChangedEventArgs("Count"));
}