0

I've the following problem: if I load a simple list into ICollectionView which is bound on my wpf listbox, then CurrentChanged event being raised as I expected:

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

However, Imagine I'm loading data into another thread, then, I would like the same behaviors, that is raising currentChanged event, but it doesn't work:

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

Note that I'm using TaskScheduler.FromCurrentSynchronizationContext() in order to work on UI thread, however it doesn't work. I also tried with Application.Current.Dispatcher.Invoke without luck.

bit
  • 934
  • 1
  • 11
  • 32

1 Answers1

0

I think that the root cause is inside your xaml.

If you are using <ListBox />, or any other ItemsControl, that inhireted from Selector, try to set IsSynchronizedWithCurrentItem to True, like this:

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

I have tried this, and this works fine, with and without TPL Task

In the MainWindow.xaml.cs I have this (try it, the xaml should contain the ListBox mentioned above):

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));
    }
}
stukselbax
  • 5,855
  • 3
  • 32
  • 54
  • I've already set IsSynchronizedWithCurrentItem to true, however just like my code snippet, it doen't work. I'm using visual studio 2012 and .NET Frameork 4.0 – bit Jul 14 '14 at 16:48
  • I've just used your code and as I expected,it doen't work. Now I'm using VS 2013 with .NET 4.5. It seems impossibile! – bit Jul 14 '14 at 17:21
  • I've solved by replacing TaskScheduler.FromCurrentSynchronizationContext()) with TaskScheduler.Current. – bit Jul 14 '14 at 19:31