[英]Observable Collection Property Changed on Item in the Collection
I have an ObservableCollection<T>
. 我有一个
ObservableCollection<T>
。 I've bound it to a ListBox control and I've added SortDescriptions
to the Items collection on the ListBox to make the list sort how I want. 我已将它绑定到ListBox控件,我已将
SortDescriptions
到ListBox上的Items集合中,以使列表按我的方式排序。
I want to resort the list at ANY point when any property changed on a child element. 当任何属性在子元素上发生更改时,我想在任何时候使用列表。
All my child elements implement INotifyPropertyChanged
. 我的所有子元素都实现了
INotifyPropertyChanged
。
Brute force: 蛮力:
EDIT: 编辑:
The code for 1, 2 would live in your code-behind. 1,2的代码将存在于您的代码隐藏中。
For #1, you'd do something like: 对于#1,您可以执行以下操作:
private void Source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach( SomeItem item in e.NewItems)
{
item.PropertyChanged += new PropertyChangedEventHandler(_SomeItem_PropertyChanged);
}
break;
....
**HANDLE OTHER CASES HERE**
....
}
}
For #2, in your CollectionChanged handler, you would do something like: 对于#2,在CollectionChanged处理程序中,您可以执行以下操作:
private void _SomeItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
ListCollectionView lcv = (ListCollectionView)(CollectionViewSource.GetDefaultView(theListBox.ItemsSource));
lcv.Refresh();
}
EDIT2: However, in this case, I would strongly suggest that you also check ListCollectionView.NeedsRefresh and only refresh if that is set. EDIT2:但是,在这种情况下,我强烈建议您也检查ListCollectionView.NeedsRefresh并仅在设置时刷新。 There's no reason to re-sort if your properties have changed which don't affect the sort.
如果您的属性已更改而不影响排序,则没有理由重新排序。
This works. 这有效。 Whenever the collection changes, it re-sorts the collection.
每当集合发生变化时,它都会重新对集合进行排序。 Might be doable in a more efficient way but this is the gist of it.
可能以更有效的方式实现,但这是它的要点。
public partial class TestWindow : Window {
ObservableCollection<TestClass> oc;
public TestWindow() {
InitializeComponent();
// Fill in the OC for testing
oc = new ObservableCollection<TestClass>();
foreach( char c in "abcdefghieeddjko" ) {
oc.Add( new TestClass( c.ToString(), c.ToString(), c.GetHashCode() ) );
}
lstbox.ItemsSource = oc;
// Set up the sorting (this is how you did it.. doesn't work)
lstbox.Items.SortDescriptions.Add( new SortDescription("A", ListSortDirection.Ascending) );
// This is how we're going to do it
oc.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( oc_Sort );
}
void oc_Sort( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e ) {
// This sorts the oc and returns IEnumerable
var items = oc.OrderBy<TestClass, int>( ( x ) => ( x.C ) );
// Rest converst IEnumerable back to OC and assigns it
ObservableCollection<TestClass> temp = new ObservableCollection<TestClass>();
foreach( var item in items ) {
temp.Add( item );
}
oc = temp;
}
private void Button_Click( object sender, RoutedEventArgs e ) {
string a = "grrrr";
string b = "ddddd";
int c = 383857;
oc.Add( new TestClass( a, b, c ) );
}
}
public class TestClass : INotifyPropertyChanged {
private string a;
private string b;
private int c;
public TestClass( string f, string g, int i ) {
a = f;
b = g;
c = i;
}
public string A {
get { return a; }
set { a = value; OnPropertyChanged( "A" ); }
}
public string B {
get { return b; }
set { b = value; OnPropertyChanged( "B" ); }
}
public int C {
get { return c; }
set { c = value; OnPropertyChanged( "C" ); }
}
#region onpropertychanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged( string propertyName ) {
if( this.PropertyChanged != null ) {
PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}
}
#endregion
}
XAML: XAML:
<Window x:Class="ServiceManager.TestWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="TestWindow" Height="500" Width="500"> <DockPanel> <ListBox ItemsSource="{Binding}" x:Name="lstbox"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Label Content="{Binding Path=A}"/> <Label Content="{Binding Path=B}"/> <Label Content="{Binding Path=C}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <Button Click="Button_Click" Content="Click" /> </DockPanel> </Window>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.