【问题标题】:MVVM call async method on selection changeMVVM 在选择更改时调用异步方法
【发布时间】:2018-09-21 23:06:49
【问题描述】:

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

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

我有一个异步方法,我想在选择更改时运行它

async Task foo();

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

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

Task.Run inside set 是一个选项,但在我看来仍然很糟糕,foo 抛出的异常会膨胀

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

【问题讨论】:

  • 我会使用异步 SelectedChanged 事件处理程序,它调用 DataContext 中的异步方法。
  • @Clemens 作为最纯粹的 MVVM 我想尽量减少背后代码的使用
  • 后面的最小代码是await ((ViewModel)DataContext).SomeAsyncMethod(listBox.SelectedItem);
  • @Clemens 让我改写一下。后面的空代码将是我的最终目标..
  • @Clemens 希望找到一种通过交互 + 动作实现此目的的方法

标签: c# wpf mvvm


【解决方案1】:

如果你想要零代码的方法,我会这样做。

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

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

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

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

【讨论】:

    【解决方案2】:

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

    类似

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

    【讨论】:

      猜你喜欢
      • 2018-01-16
      • 2019-08-17
      • 2020-03-30
      • 2018-10-01
      • 2020-08-12
      • 1970-01-01
      • 2020-08-18
      • 2016-08-25
      • 2020-05-16
      相关资源
      最近更新 更多