如何在双向绑定Combobox(WPF)上调用异步操作

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (37)

当从双向绑定控件(如组合框(wpf data binding))中选择项时,处理异步操作的适当方法是什么?

当我有一个双向绑定属性(例如ComboBox上的SelectedValue)时,我认为我不能使用Stephen Cleary的NotifyTaskCompletion, 因为当用户从下拉列表中选择一个值时,ComboBox本身需要修改绑定的Result属性,是任务的结果。

我提出的唯一可行的解​​决方案是在不等待结果的情况下从数据绑定设置器调用异步任务方法。这应该没问题,只要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();
    }
}

注意:我发现了类似的问题,但是没有一个问题解决了对象(如Combobox)的双向绑定问题。

提问于
用户回答回答于

async使用WCF数据绑定时,我在属性设置器中调用时遇到了类似的问题。我的解决方案略胜一筹,因为在您遇到异常的情况下InitializeAsyncAndFirePropertyChanged,不会抛出或捕获任何异常。修改后的代码如下。它使用任务继续来抛出异常并提升OnPropertyChangedOnPropertyChanged电话可以留在原来的地方,这取决于你的需求。

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
}
用户回答回答于

如果您正在使用功能性的反应性MVVM框架(如ReactiveUI),则只需观察该SelectedItem属性,并在设置该属性时启动所需的任何操作。例如:

this.WhenAnyValue(x => x.SelectedItem)
    .Subscribe(async _ => await InitializeAsyncAndFirePropertyChanged());

属性本身应该开始后台操作,但是视图模型可以在设置属性时执行此操作。

有关更多信息,请参阅文档:https//reactiveui.net/docs/concepts/

扫码关注云+社区

领取腾讯云代金券