0

次の問題があります。wpf リストボックスにバインドされている ICollectionView に単純なリストをロードすると、期待どおりに CurrentChanged イベントが発生します。

List<int> l = new List<int>();
l.Add(1);
l.Add(2);
MyCollection = CollectionViewSource.GetDefaultView(l);
MyCollection.CurrentChanged += MyCollection_CurrentChanged; // ok, it's raised

ただし、データを別のスレッドにロードしていると想像してください。次に、 currentChanged イベントを発生させる同じ動作が必要ですが、機能しません。

 List<int> l = new List<int>();
            Task.Factory.StartNew(() =>
            {
                l.Add(1);
                l.Add(2);
            })
            .ContinueWith((r) => 
                {

                    MyCollectio = CollectionViewSource.GetDefaultView(l);
                    MyCollectio.CurrentChanged += MyCollectio_CurrentChanged; // ko, it isn't raised.

                }, TaskScheduler.FromCurrentSynchronizationContext());

UIスレッドで作業するために TaskScheduler.FromCurrentSynchronizationContext() を使用していますが、機能しないことに注意してください。私も Application.Current.Dispatcher.Invoke を試してみましたが、うまくいきませんでした。

4

1 に答える 1

0

根本的な原因は xaml 内にあると思います。

Selectorから継承した<ListBox />またはその他のItemsControlを使用している場合は、次のようにIsSynchronizedWithCurrentItemTrueに設定してみてください。

<ListBox ItemsSource="{Binding MyCollectio}"
         IsSynchronizedWithCurrentItem="True"
         />

私はこれを試しましたが、これはTPL タスクの有無にかかわらず正常に動作します

MainWindow.xaml.cs にはこれがあります (試してみてください。xaml には上記のListBoxが含まれている必要があります)。

public MainWindow()
{
    InitializeComponent();

    MyVM con = new MyVM();
    DataContext = con;
    List<int> l = new List<int>();
    Task.Factory.StartNew(() =>
    {
        l.Add(1);
        l.Add(2);
        l.Add(3);
        l.Add(4);
        l.Add(5);
        l.Add(6);
    })
    .ContinueWith((r) =>
    {

        con.MyCollectio = CollectionViewSource.GetDefaultView(l);
        con.MyCollectio.CurrentChanged += MyCollectio_CurrentChanged;
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

void MyCollectio_CurrentChanged(object sender, EventArgs e)
{
    MessageBox.Show("Curren really changed!!!");
}

...

public class MyVM : ViewModelBase
{
    public ICollectionView MyCollectio
    {
        get
        {
            return _MyCollectio;
        }

        set
        {
            _MyCollectio = value;
            RaisePropertyChanged("MyCollectio");
        }
    }
    private ICollectionView _MyCollectio;
}

...

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
于 2014-07-14T16:06:04.160 に答える