MVVM在选择更改时调用异步方法

时间:2018-09-21 14:43:05

标签: c# wpf mvvm

我有一个简单的列表框,其中选定的项绑定到ViewModel的属性

<ListBox SelectedItem="{Binding SelectedItem, Mode=TwoWay}">

并且我有一个异步方法,当选择更改时我想运行该方法

async Task foo();

我可以将此呼叫放在SelectedItem的设置器中,但这对我来说是代码的味道。

public object SelectedItem
{
    get{...}
    set
    {
         foo(); //Compiler warning and blocks UI
         ...
    }
}

Task.Run在set内部是一个选项,但对我来说仍然很糟糕,foo引发的异常将肿胀

SelectionChanged事件后面的代码可能是另一个选择,但是解决该问题的最MVVM方法是什么?

2 个答案:

答案 0 :(得分:2)

如果您想要后面带有零代码的方法,这就是我要做的。

使用Interaction将SelectedItemChanged事件转换为命令。

这是有关如何将事件转换为命令的代码

   <i:Interaction.Triggers>
        <i:EventTrigger EventName="SomeEvent">
            <i:InvokeCommandAction Command="{Binding Path=SomeCommand, Mode=OneWay}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

然后,您在视图模型中的命令将阻止UI并调用异步功能。

答案 1 :(得分:0)

我将设置一个事件处理程序。

类似

 public class ViewModel:INotifyPropertyChanged
{

    public ViewModel()
    {
        PropertyChanged += SelectedItemChanged;
    }

    private async void SelectedItemChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(SelectedItem))
        {
            await Foo();
        }
    }

    public Task Foo()
    {
        return Task.Run(() =>
        {
            var a = "B";
        });
    }

    private object _selectedItem;

    public object SelectedItem
    {
        get=> _selectedItem;
        set
        {
            if (value != _selectedItem)
            {
                _selectedItem = value;
                OnPropertyChanged();
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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