我用this blog(最後一段)與INotifyTaskCompletion
方法有一個視圖模型的異步性。它很好地工作,但我不得不適應它有一個謊言我的問題 - 我是否正確地做了它。額外的PropertyChanged需要INotifyTaskCompletion後完成其任務
視圖模型:
async Task<ObservableCollection<string>> GetInstancesAsync()
{
var instances = await TaskEx.Run(new Func<List<string>>(() => Agent.GetInstances()));
return new ObservableCollection<string>(instances);
}
public INotifyTaskCompletion<ObservableCollection<string>> InstancesAsync { get; private set; }
string instance;
public string Instance
{
get { return instance; }
set
{
instance = value;
ProjectsAsync = NotifyTaskCompletion.Create(GetProjetsAsync(value));
raisePropertyChanged("ProjectsAsync");
}
}
在構造函數中我開始:
InstancesAsync = NotifyTaskCompletion.Create(GetInstancesAsync(value));
raisePropertyChanged("InstancesAsync");
數據綁定僅僅是ItemsSource="{Binding InstancesAsync.Result}"
。 的INotifyTaskCompletion<TResult>
的實現並不複雜,簡稱:task.ContinueWith(t => { PropertyChanged(this, new PropertyChangedEventArgs("Result")); };
我的理解如下:啓動任務之後,raisePropertyChanged("InstancesAsync")
有WPF試圖找到InstancesAsync.Result
效果。它發現InstancesAsync
,因爲此對象實例化之前任務啓動,但結果是null。完成任務後,wpf收到PropertyChanged("Result")
,並通過現有訪問者InstancesAsync
Result
現在被發現。
wpf中的ItemsSource已填充,現在wpf必須觸發SelectedItem的綁定,並以此方式轉至屬性Instance
。因爲在我的情況下,啓動了另一個異步屬性任務。 要完成這個任務,我需要在任務完成後啓動raisePropertyChanged("Instance")
。
我解決了這個問題,將我的raisePropertyChanged
作爲委託,將屬性名稱作爲字符串傳遞給實現類INotifyTaskCompletion
。
我很滿意這個解決方案,但也許我忽略了一些東西?
編輯:
原來,克萊裏先生的直接方式是正確的,但只有當IsSynchronizedWithCurrentItem=True
。否則,不會自動選擇列表中的第一項。
另一個相關的問題彈出。
我加入INotifyTaskCompletion
支票if (propertyChanged == null) throw new Exception("PropertyChanged: no subscribers");
,因爲我之前遇到過這個問題。
然後在Instance
二傳手我說:
private string _instance;
public string Instance
{
get { return _instance; }
set
{
if (ProjectsAsync == null && !Properties.Settings.Default.Instance.IsNullOrEmpty())
{
value = InstantiesAsync.Result.FirstOrDefault(i => i == Properties.Settings.Default.Instance);
}
_instance = value;
raisePropertyChanged("Instance");
ProjectsAsync = NotifyTaskCompletion.Create(GetProjetsAsync(value));
}
}
這裏的想法是重寫底層ICollectionView
項目0的默認選擇。
然後我提到的例外發生。我有操縱ICollectionView
的CurrentItem
,而不是隨意更改值。有任何想法嗎?
我目前的解決方案是避免IsSynchronizedWithCurrentItem=True
乾脆當列表被設爲一個新的值設置列表的的SelectedItem。
因此,我不得不訂閱異步PropertyChanged事件:
instancesAsync.PropertyChanged += instancesAsync_Ready;
還有:
if (e.PropertyName == "Result")
{
if (instance == null && !Properties.Settings.Default.Instance.IsNullOrEmpty())
{
Instance = InstancesAsync.Result.FirstOrDefault(i => i == Properties.Settings.Default.Instance);
}
}
你是對的,它的工作原理。另一個相關問題現在出現了,也許你可以看看我編輯的問題。 – Gerard
刪除你的'PropertyChanged:no subscribers'異常。如果一個屬性發生了變化,那麼如果沒有人在傾聽,它應該*不會*引發異常。 –
我同意,對於我確定某些問題,例如改變/創建一個對象,例如'_instancesAsync'錯誤。 Evertything現在完美地工作,感謝支持。 – Gerard