Если вы включили виртуализацию, потому что время загрузки сетки данных ужасно, то вот решение:
- отключить виртуализацию
давайте предположим / назовем привязку источника элементов вашей таблицы данных как "Rows",
public IEnumerable<Row> Rows {get; set;}
Добавьте свойство в свой класс «Row» IsVisible и переключайте его, когда вы хотите загрузить данные (не тогда, когда поток пользовательского интерфейса решит разрешить привязку и загрузить каждый элемент управления)
причина, по которой это работает, заключается в том, что когда вы загружаете сетку, она проверяет привязку, все строки невидимы, поэтому потоку пользовательского интерфейса не нужно прокручивать все столбцы ваших строк *, чтобы создать их, он может перейти к Следующее, что нужно сделать. Вы, с другой стороны, можете определить, когда удобное время, чтобы превратить эти строки в видимые, когда View.Visibility видима, когда ViewModel загрузил данные откуда-то и т. Д. Таким образом, вы находитесь в полном контроле. Ниже я перебираю свой источник элементов (строки) с помощью задачи (в фоновом потоке), но настраиваю видимость в потоке пользовательского интерфейса.
private _isVisible = false;
/// <summary>
/// is false by default, for performance when loading first time.
/// </summary>
public bool IsVisible
{
get { return _isVisible; }
set
{
if (_isVisible == value)
return;
_isVisible = value;
RaisePropertyChanged(() => IsVisible);
}
}
В представлении, когда сетка данных загружается, не позволяйте ему перегружать поток пользовательского интерфейса, помещая итерацию строк в фоновый поток, а затем установите для параметра Видимость значение true. Даже если вы находитесь в фоновом потоке, измененное свойство IsVisible приведет к обновлению.
private void OnGridLoaded(object sender, RoutedEventArgs e)
{
//sample bool checks, you might not need them...
if (firstTimeLoad && !_isDataGridLoaded)
{
Task.Factory
.StartNew(() =>
{
/*first time loading performance tweak*/
foreach (var row in _viewModel.Rows)
ExeOnUi(() => { row.IsVisible = true; });
_firstTimeLoad = false;
})
}
забыл добавить код ExeOnUi (вы можете проверить доступ, используя что-то еще, например whatControl.Dispatcher.CheckAccess, я просто использую Microsoft.Practices.ServiceLocator):
static void ExeOnUi (Action action)
{
var srv= ServiceLocator.Current.GetInstance<IDispatchService> ();
if (srv.CheckAccess ())
action.Invoke ();
else
srv.Invoke (action);
}