【问题标题】:Run async method from Xaml从 Xaml 运行异步方法
【发布时间】:2016-10-25 08:52:23
【问题描述】:

我如何从 Xaml 运行异步方法(单击时),通常我使用这样的东西:

xmlns:ii="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
             xmlns:eii="http://schemas.microsoft.com/expression/2010/interactions"

<Button Height="30" Width="200" Content="Save" >
                <ii:Interaction.Triggers>
                    <ii:EventTrigger EventName="Click">
                        <eii:CallMethodAction TargetObject="{Binding}" MethodName="Saveing"/>
                    </ii:EventTrigger>
                </ii:Interaction.Triggers>
            </Button>

保存方法:

public async Task Saveing(){...}

【问题讨论】:

  • 按钮有点击,所以不需要这个交互触发器,你只需在事件处理程序中添加 async 关键字。
  • 在 mvvm 应用程序中?
  • 在这种情况下,按钮可以绑定到命令。然后命令有一个可以是异步的动作。您可以使用 Prism 或 MVVMLIGHT 之类的工具来使用它们的命令。
  • @P10trek MVVM 意味着后面的控件代码不应该说明它如何处理数据,有一个将指令传递给视图模型的事件是完全正确的

标签: c# wpf xaml mvvm prism


【解决方案1】:

MVVM 的重点是将 UI 与处理分离。

将按钮的 Command 属性绑定到 ViewModel 中的 ICommand(RelayCommand 或其他实现)项。可以以async 的方式调用此命令的关联方法。例如

public ICommand SaveCommand {get; private set;}

private async Task SaveMethodAsync() 
{
    await dbService.SaveDataAsync(modelItem).ConfigureAwait(false);
    ...
}


public ViewModel()
{
    SaveCommand = new RelayCommand(async () =>
        await SaveMethodAsync().ConfigureAwait(false));
}

【讨论】:

    【解决方案2】:

    XAML 不应该运行任何东西,它应该只是通知视图模型需要运行一些东西,一种方法是将事件连接到点击事件,但是另一种可能更好的方法是使用 CommandBinding

    Button 有一个 Command 属性,如果你有一个实现 ICommand 的代码对象,那么你可以使用命令绑定来触发动作

    例子

    public interface ISavable
    {
        void Save();
        SaveCommand SaveCommand { get; }
    }
    public class SaveCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;
    
        public bool CanExecute(object parameter)
        {
            return parameter is ISavable;
        }
    
        public void Execute(object parameter)
        {
            Task.Run(()=>((ISavable)parameter).Save());
        }
    }
    

    XAML:

    <Button Command="{Binding SaveCommand}" CommandParameter="{Binding}" />
    

    这样,任何实现ISavable 的视图模型都将在没有代码的情况下连接起来

    【讨论】:

      【解决方案3】:

      只需重写你的方法如下:

      public void Saving() 
      {
          Task.Run(async () => {...});
      }
      

      【讨论】:

      • 为什么不返回接受的答案中的任务?后台线程的异常会发生什么?
      猜你喜欢
      • 1970-01-01
      • 2020-02-07
      • 2021-04-15
      • 1970-01-01
      • 2016-12-02
      • 1970-01-01
      • 1970-01-01
      • 2020-05-13
      相关资源
      最近更新 更多