简体   繁体   English

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

[英]MVVM call async method on selection change

I have a simple list box with selected Item binded to ViewModel's property 我有一个简单的列表框,其中的选定项绑定到ViewModel的属性

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

and I have an async method that I want to run when the selection changed 而且我有一个异步方法,当选择更改时,我想运行该方法

async Task foo();

I could put this call inside the setter for SelectedItem but that's a code smell to me. 我可以将这个调用放在SelectedItem的设置器中,但这对我来说是代码的味道。

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

Task.Run inside set is an option, but still looks bad to me and exception thrown by foo will be swollen Task.Run在set中运行是一个选项,但对我来说仍然很糟糕,并且foo引发的异常会肿胀

Code behind SelectionChanged event might be another option but whats the most MVVM way to solve this problem? SelectionChanged事件背后的代码可能是另一个选择,但是解决该问题的最MVVM方法是什么?

If you want the approach with zero code behind, here is what I would do. 如果您想使用零代码的方法,这就是我要做的。

Convert the SelectedItemChanged event to a command using Interaction. 使用Interaction将SelectedItemChanged事件转换为命令。

Here is code on how you can convert an event to a command 这是有关如何将事件转换为命令的代码

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

Your command in the view model will then block the UI and invoke the async functionality. 然后,视图模型中的命令将阻止UI并调用异步功能。

I would set up an event handler. 我将设置一个事件处理程序。

something like 就像是

 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));
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM