当从双向绑定控件(如combobox (wpf数据绑定))中选择一个项时,处理运行异步操作的适当方式是什么?
当我有一个双向绑定属性(例如ComboBox上的SelectedValue )时,我不认为我可以使用Stephen Cleary's NotifyTaskCompletion,因为当用户从下拉列表中选择一个值时,ComboBox本身将需要修改绑定结果属性,这是任务的结果。
我想出的唯一可行的解决方案是在不等待结果的情况下从数据绑定设置器调用异步任务-method。只要async-method触发与ui相关的任何东西的属性更改事件,并且任何异常都会被拾取并相应地传播到ui,就应该没问题,对吧?
我假设这将是异步WPF应用程序中的常见情况。你们是怎么解决这个问题的?
到目前为止我的解决方案是:
<ComboBox
ItemsSource="{Binding PossibleItems}"
DisplayMemberPath="Name"
SelectedValue="{Binding SelectedItem}"/>
..。
public Item SelectedItem
{
get { return m_selectedItem; }
set
{
m_selectedItem = value;
OnPropertyChanged();
InitializeAsyncAndFirePropertyChanged(); // async Task method not awaited - gives compiler warning CS4014
}
}
public async Task InitializeAsyncAndFirePropertyChanged(ObservableCollection<RFEnvironment> possibleRfEnvironments)
{
//should check this method for exceptions and propagate them to the UI via databinding
OtherDataBoundProperty = await GetSomeStringFromWebAsync();
}
public string OtherDataBoundProperty
{
get { return m_otherDataBoundProperty; }
set
{
m_otherDataBoundProperty = value;
OnPropertyChanged();
}
}
注意:我发现了类似的问题,但没有一个涉及控件上的双向绑定,例如组合框。
发布于 2018-01-25 21:35:33
如果您使用的是函数式反应式MVVM框架,如ReactiveUI,则只需观察SelectedItem
属性,并在设置该属性时启动所需的任何操作。例如:
this.WhenAnyValue(x => x.SelectedItem)
.Subscribe(async _ => await InitializeAsyncAndFirePropertyChanged());
属性本身应该启动后台操作,但视图模型可以在设置属性时执行此操作。
有关更多信息,请参阅文档:https://reactiveui.net/docs/concepts/。
发布于 2019-05-20 22:31:17
当使用WCF数据绑定时,我在属性设置器中的async
调用也有类似的问题。我的解决方案稍微好一点,因为在您的示例中,当InitializeAsyncAndFirePropertyChanged
中发生异常时,不会抛出或捕获任何异常。修改后的代码如下。它使用任务继续抛出异常并引发OnPropertyChanged
。OnPropertyChanged
调用可以停留在原来的位置,这取决于您的需求。
public class MyViewModel: INotifyPropertyChanged
{
private readonly TaskScheduler _uiScheduler;
public MyViewModel()
{
_uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
}
public Item SelectedItem
{
get { return m_selectedItem; }
set
{
m_selectedItem = value;
InitializeAsyncAndFirePropertyChanged()
.ContinueWith(t =>
{
if (t.Exception != null)
{
throw t.Exception;
}
OnPropertyChanged();
}, _uiScheduler);
}
}
public async Task InitializeAsyncAndFirePropertyChanged(ObservableCollection<RFEnvironment> possibleRfEnvironments)
{
//should check this method for exceptions and propagate them to the UI via databinding
OtherDataBoundProperty = await GetSomeStringFromWebAsync();
}
public string OtherDataBoundProperty
{
get { return m_otherDataBoundProperty; }
set
{
m_otherDataBoundProperty = value;
OnPropertyChanged();
}
}
.... other code to support INotifyPropertyChanged
}
https://stackoverflow.com/questions/48423750
复制相似问题