WPF-单击一个按钮即可执行多项操作

问题描述 投票:0回答:1

我正在努力学习WPF并试图找出最佳做法。我了解基本的教程,但它们通常不会涵盖更多的“复杂”行为。

我的用例如下:用户输入许可证密钥,然后单击“确定”按钮。在后台,我必须异步调用一个Web API,该API将返回一个对象(LicenseCheckResult),其中包含有关所提供许可证的详细信息(到期,类型,...)。如果许可证密钥有效,则将其存储。然后相应地更新UI(与许可证相关的用户控件的显示根据LicenseCheckResult对象而改变)。

由于检查许可证的调用是异步的,因此我使用了此处描述的IAsyncCommand(https://docs.microsoft.com/en-us/archive/msdn-magazine/2014/april/async-programming-patterns-for-asynchronous-mvvm-applications-commands

这是代码,在我的MainWindowViewModel中,我有:

 public IAsyncCommand _checkLicenseCommand;

 public IAsyncCommand CheckLicenseCommand { get; private set; }

 public async Task<LicenseCheckResult> CheckLicense(CancellationToken token)
 {
      var task = await _licenseCheckProvider.CheckLicenseAsync(_generalSettings.ID, LicenseKey, token);
      if (task.Status == LicenseStatus.Valid.ToString())
      { 
           _generalSettings.LicenseKey = _encryptionProvider.Encrypt(LicenseKey); // Store license key
           SettingLicense = false; // toggle the license key input modal dialog
      }
      return task;
 }

 public MainWindowViewModel(IOptions<GeneralSettings> generalSettings, IEncryptionProvider encryptionProvider, ILicenseCheckProvider licenseCheckProvider)
 {
      _generalSettings = generalSettings.Value;
      _licenseCheckProvider = licenseCheckProvider;
      _encryptionProvider = encryptionProvider;

      CheckLicenseCommand = AsyncCommand.Create(token => CheckLicense(token));

      ... other stuff
 }

[CheckLicenseCommand已绑定到“确定”按钮。

在主窗口XAML中,LicensingUserControl的可见性绑定到IAsyncCommand的任务

<StackPanel Orientation="Vertical">
    <StackPanel Orientation="Vertical" Visibility="{Binding CheckLicenseCommand.Execution, Converter={StaticResource NullToVisibilityConverter}}">
        <localControls:LicensingUserControl HorizontalAlignment="Stretch" VerticalAlignment="Top" Visibility="{Binding CheckLicenseCommand.Execution.IsSuccessfullyCompleted, Converter={StaticResource boolTovisibility}}" />
    </StackPanel>
    ... other stuff
</StackPanel>

在LicensingUserControl中,显示绑定到IAsyncCommand返回的任务的结果:

<Grid x:Name="LayoutRoot" Background="{Binding CheckLicenseCommand.Execution.Result.Background}">
    <StackPanel x:Name="MainStackPanel" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="2" >
        <TextBlock Text="Type:" Width="Auto" VerticalAlignment="Center" TextAlignment="Right" FontWeight="Bold" Margin="0"/>
        <Label Content="{Binding CheckLicenseCommand.Execution.Result.Type}" VerticalAlignment="Center" Width="Auto" Margin="0"/>
        <TextBlock Text="License:" Width="Auto" VerticalAlignment="Center" TextAlignment="Right" FontWeight="Bold" Margin="0"/>
        <Label Content="{Binding CheckLicenseCommand.Execution.Result.Status}" VerticalAlignment="Center" Width="Auto" Margin="0"/>

        ... other stuff

这可以运行,但是CheckLicense方法可以吗? (我正在等待此方法中的任务,以便能够使用异步调用的结果,然后将任务返回给UI以进行更新。)如果没有,那么这样做的正确方法是什么?

此外,我是否应该研究一种框架来帮助更复杂的行为(我正在使用.Net Core?

c# wpf icommand
1个回答
0
投票

您使用非常复杂的行为,我认为您的方法有误。但是,如果我想回答您的问题,只需继承MainWindowViewModel中的INotifyPropertyChanged接口,然后在CheckLicenseCommand的CheckLicense中调用OnPropertyChanged:

 public event PropertyChangedEventHandler PropertyChanged;

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

 public async Task<LicenseCheckResult> CheckLicense(CancellationToken token)
 {
      var task = await _licenseCheckProvider.CheckLicenseAsync(_generalSettings.ID, LicenseKey, token);
      if (task.Status == LicenseStatus.Valid.ToString())
      { 
           _generalSettings.LicenseKey = _encryptionProvider.Encrypt(LicenseKey); // Store license key
           SettingLicense = false; // toggle the license key input modal dialog
      }
      OnPropertyChanged(nameof(CheckLicenseCommand));

      return task;
 }
© www.soinside.com 2019 - 2024. All rights reserved.