У меня есть WPF DataGrid
, который привязан к ViewModel, и все отлично. Теперь я понимаю, что мне нужно загрузить намного больше данных в DataGrid
, чем раньше. Поэтому я использовал async
, чтобы сделать загрузку этих данных в блокировку контейнера Viewmodel, отличную от UI. Так, в моем ResourceDataViewModel : ViewModelBase
у меня есть следующий методАсинхронный метод, вызывающий странное исключение
public async void LoadResourceFilesAsync(string fullFileName = null)
{
if (!String.IsNullOrEmpty(fullFileName))
this.FullFileName = fullFileName;
strategy = manager.InitialiseStrategy(this);
if (strategy == null)
return;
...
// Get data asynchoniously.
List<ResourceViewModel> resourceViewModelList = await strategy.LoadResourceFilesAsync();
this.Resources = new TypedListObservableCollection<ResourceViewModel>(resourceViewModelList);
// Setup event handlers.
this.Resources.CollectionChanged += this.OnCollectionChanged;
foreach (ResourceViewModel rvm in resourceViewModelList)
rvm.PropertyChanged += this.OnResourceViewModelPropertyChanged;
// Set the file name for View and ViewModel.
this.FullFileName = strategy.FullFileName;
base.DisplayName = Path.GetFileName(this.FullFileName);
...
}
Итак, перед моим делает метод загрузки async
, все было хорошо; данные были загружены и DisplayName
(свойство, определенное в классе abstract
ViewModelBase
), которое связано с свойством заголовка TabItem
, вызвало правильное отображение имени файла в заголовке TabItem
. Теперь я сделал asynchronious нагрузки, нагрузки данных в DataGrid
штрафа, как вы ожидали бы сформировать код, указанный выше, однако,
base.DisplayName = Path.GetFileName(this.FullFileName);
не обновляет base.DisplayName
вместо этого он молча (т.е. не бросает и Exeption в моем коде) вызывает System.ArgumentException
с сообщением:
Сообщение = "Невозможно найти метод на экземпляре объекта".
Теперь я изменил base.DisplayName
к **this**.DisplayName
и это останавливает исключение, но до сих пор не обновлять TabItem
Header
, почему это происходит и как это исправить?
Примечание. Я проверил Thread, на котором это выполняется, и это MainThread/UIThread, как ожидалось, что делает это довольно аномальным.
Обновление. Я использовал Snoop, чтобы получить крючок в том, что происходит со связыванием, когда я использую this.DisplayName
, и привязка показывает {DisconnectedItem}
(я нашел related question at MSDN). Однако я до сих пор в недоумении относительно того, что происходит здесь ...
правок Адрес Комментарии
DataContext
моих приложений MainWindow является MainWindowViewModel
; это содержит свойство
public ObservableCollection<WorkspaceViewModel> Workspaces { ... }
который держит ViewModels я хочу, чтобы отобразить в каждом TabItem
. У меня есть еще один ViewModel (так называемый ResourceDataViewModel ) which holds the
DataGrid s and inherits from
общественного WorkspaceViewModel`, который определяется как
public abstract class WorkspaceViewModel : ViewModelBase { ... }
и обрабатывает все MVVM такие вещи, как OnPropertyChanged
обработчиков и т.д. В MainWindowViewModel
иерархии вызовов, чтобы загрузить файл ресурса в к TabControl
в главное окно:
public void LoadResourceFiles(string fullFileName = null)
{
// Build and load the ViewModel in to the View.
ResourceDataViewModel workspace = new ResourceDataViewModel(this);
workspace.LoadResourceFilesAsync(fullFileName);
...
}
и в ResourceDataViewModel
у меня есть метод, показанный на оригинальный вопрос выше.Это затем получает стратегию от стратегии завода и загружает асинхра данных - в этом случае, используя следующие методы
public async Task<List<ResourceViewModel>> LoadResourceFilesAsync()
{
// Do preliminary work here [build FileCultureDictionary etc.].
...
// Build the resource data sets and return.
List<Resource> buildResult = await BuildResourceDataAsync(FileCultureDictionary);
return (from resource in buildResult
select new ResourceViewModel(resource)).ToList();
}
private async Task<List<Resource>> BuildResourceDataAsync(Dictionary<string, string> cultureDict)
{
// Now add the data.
int fileIndex = 1;
const int coreColumnIndex = 2;
string[] strArr = null;
List<string[]> strArrList = new List<string[]>();
// Start building the data.
Task<List<Resource>> task = Task.Factory.StartNew<List<Resource>>(() =>
{
// Do some work here...
...
return resources;
});
return await task;
}
Обратите внимание, что данные, которые поступают обратно из этих методов прекрасно. Эти методы сами по себе, по-видимому, не вызывают проблемы выше, но может быть и переключением контекста. Я нахожусь в настоящей потере здесь, поэтому любые идеи приветствуются.
Итак, @svick любые идеи? – MoonKnight
Ну, вы почти никогда не должны использовать методы async void, но я не думаю, что это исправит вашу проблему. – svick
Почему вы никогда не должны их использовать? Они были предназначены для использования, не так ли? – MoonKnight