簡體   English   中英

在調用 ShowDialog 之后/期間使用異步值更新 ViewModel

[英]Update ViewModel with async value, after/during call to ShowDialog

我正在創建一個模態 window,將它的DataContext分配給我的視圖 model,然后調用ShowDialog

var vm = new MyViewModel();  // implements INotifyPropertyChanged

// populate vm properties here

var window = new MyWindow(); // inherits from System.Windows.Window
window.DataContext = vm;
window.ShowDialog();

但是,我想從async方法的結果中填充視圖模型的屬性。

vm.Result = await provider.GetResultAsync();

我希望這些更改對 window 中的數據綁定屬性可見。

在調用ShowDialog之前我不能這樣做,因為只有在結果可用后才會調用ShowDialog

在調用ShowDialog后我不能這樣做,因為ShowDialog會阻塞,直到 window 關閉。

我怎樣才能做到這一點?

將此代碼移入 MyWindow Class

然后在 window_loaded()

var vm = new MyViewModel();  // implements INotifyPropertyChanged

// populate vm properties here

this.DataContext = vm;

您可以通過多種方式做到這一點。 我推薦@WowoOt 的答案,因為視圖 model 必須是您嘗試使用的 window 的一部分。

另一種實現方式是在provider.GetResultAsync()的調用中使用Task.ContinueWith方法,然后在回調中寫入vm.Result = task.Response 但是,這僅在您的視圖 model 實現INotifyPropertyChanged時才有效。

這是此的代碼:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
    // Supposed to open the window after clicking a button.
    var vm = new MyViewModel();
    var window = new MyWindow {
        DataContext = vm
    };
    //vm.Result = await GetResultAsync();
    _ = GetResultAsync().ContinueWith(x => vm.Result = x.Result);

    window.ShowDialog();

    static async Task<string> GetResultAsync() {
        await Task.Delay(1000); // just to simulate a long process to recover the data.
        return $"generated string: {new Random().Next(10)}";
    }
}

我的示例視圖 model 實現了INotifyPropertyChanged接口,以通知 XAML 框架有關其屬性的任何更改。

public class MyViewModel : INotifyPropertyChanged {
    private string result;
    public string Result {
        get => this.result;
        set {
            this.result = value;
            this.OnPropertyChanged();
        }
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    } 
    #endregion
}

感謝@Wowo Ot 的回答@Marlonchonsky 的回答,我正在做以下事情:

var vm = new MyViewModel();
var window = new MyWindow();
window.DataContext = vm;
window.Loaded += async (s, e) => vm.Result = await provider.GetResultAsync();
window.ShowDialog();

它有效。

你可以做這樣的事情

vm.GetResultsTask = provider.GetResultsAsync();

然后,當您需要 MyWindow 中的結果時,您將await DataContext.GetResultsTask來獲取它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM