B
B
Basterrior2014-04-04 06:51:18
WPF
Basterrior, 2014-04-04 06:51:18

WPF, working with ListCollectionView in background thread - how to fix error?

There is a big table in DataGrid. The following function is executed on a background thread. First time it works. The second time swears that lcv2 belongs to another thread. How to win it?

ListCollectionView lcv2 = (ListCollectionView)CollectionViewSource.GetDefaultView(DataGrid.ItemsSource);
            if (_searchTextBoxText != null)
                lcv2.Filter = new Predicate<object>(FilterFields);
            else
                lcv2.Filter = null;
            DataGrid.Dispatcher.BeginInvoke(new Action(delegate
            {
                DataGrid.ItemsSource = lcv2;
            }));

Answer the question

In order to leave comments, you need to log in

6 answer(s)
M
Mikhail Doshevsky, 2014-04-05
@MikhailD

You cannot change the UI on threads other than the UI thread. If you need to change data in the UI from another thread, use the Dispatcher
An example of how it looks in WinRT:

Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    // Код, работающий в UI потоке
                });

S
serdceder, 2014-04-07
@serdceder

Create a separate ViewModel class, create your
own public ListCollectionView SearchResults
{
get { return _searchResults2; }
set
{
_searchResults2 = value;
RaisePropertyChanged("SearchResults");
}
}
And this is the handler for the command:
...
_searchResults2.Dispatcher.BeginInvoke(
(Action)delegate
{
_searchResults2.Filter = new Predicate(o => ...)
}, System.Windows.Threading.DispatcherPriority.Background);
SearchResults = _searchResults2;
And you will be happy. Learn to work through commands and don't combine logic and View.

S
serdceder, 2014-04-10
@serdceder

And how did you want? Of course, the interface will hang, you work directly with the UI thread, you filter the collection on the fly. There is a somewhat atrophied BackroundWorker class, but it's better to use context synchronization - it allows you to transfer data from one thread to another using events. Read the material, there is a lot of theory.

B
Basterrior, 2014-04-05
@Basterrior

Thanks for the answer, but it doesn't help me. With flows something is clear.
Here the point is that the first time it works the way I need it, and then lcv2 is transferred under the control of the UI thread. You need to somehow untie it and get rid of it altogether ... after all, it is defined only inside the function and must be somehow re-initialized at the next entry, but it turns out that lcv2.Filter = new Predicate(FilterFields); tries to work with the old variable and fails. If you put this in the dispatcher, then the meaning of the background thread is lost and the interface will slow down.

B
Basterrior, 2014-04-06
@Basterrior

Can I somehow unbind DataGrid.ItemsSource from ListCollectionView?
How would I override DataGrid.ItemsSource = lcv2;.

B
Basterrior, 2014-04-10
@Basterrior

For now, I will continue without MVVM.
I tried as it is written, only without MVVM:

Dispatcher.BeginInvoke(new Action(delegate
                    {
                lcv2.Filter = item =>
                {
                    int count = item.GetType().GetProperties().Count<object>();
                    bool result = false;
                    for (int i = 0; i < count; i++)
                        if (item.GetType().GetProperties()[i].GetValue(item, null).ToString().Contains(_searchTextBoxText))
                            result = true;
                    return result;
                };
                    }), System.Windows.Threading.DispatcherPriority.Background);

Does not help, the interface hangs.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question