我有一个简单的列表框,其中选定的项绑定到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方法是什么?
答案 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));
}
}