11

私は持っていObservableCollection<T>ます。これを ListBox コントロールにバインドし、ListBoxSortDescriptionsの Items コレクションに追加して、リストを希望どおりに並べ替えました。

子要素でプロパティが変更されたときに、任意の時点 でリストを再分類したいと考えています。

すべての子要素が実装されていINotifyPropertyChangedます。

4

2 に答える 2

12

強引な:

  1. 各子アイテムの各 PropertyChanged イベントにハンドラーをアタッチします。
  2. CollectionViewSource から ListCollectionView を取得します
  3. リフレッシュを呼び出します。

編集:

1、2 のコードはコード ビハインドに存在します。

#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**
....
      }
}

#2 については、CollectionChanged ハンドラーで次のようにします。

private void _SomeItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    ListCollectionView lcv = (ListCollectionView)(CollectionViewSource.GetDefaultView(theListBox.ItemsSource));
    lcv.Refresh();
}

EDIT2:ただし、この場合、ListCollectionView.NeedsRefresh も確認し、それが設定されている場合にのみ更新することを強くお勧めします。ソートに影響しないプロパティが変更された場合、再ソートする理由はありません。

于 2009-06-18T21:24:32.740 に答える
0

これは機能します。コレクションが変更されるたびに、コレクションが再ソートされます。もっと効率的な方法で実行できるかもしれませんが、これがその要点です。


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:

<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">
    <ドックパネル>
        <ListBox ItemsSource="{Binding}" x:Name="lstbox">
            <ListBox.ItemTemplate>
                <データ テンプレート>
                    <StackPanel Orientation="Horizo​​ntal">
                        <Label Content="{Binding Path=A}"/>
                        <Label Content="{Binding Path=B}"/>
                        <Label Content="{Binding Path=C}"/>
                    </スタックパネル>
                </データ テンプレート>
            </ListBox.ItemTemplate>
        </リストボックス>
        <Button Click="Button_Click" Content="Click" />
    </ドックパネル>
</ウィンドウ>
于 2009-06-18T21:36:48.860 に答える