MVVM在执行命令

时间:2018-12-17 16:47:16

标签: c# wpf mvvm progress-bar

我正在使用之前的question

中提供的MVVM解决方案

XAML

<ProgressBar x:Name="StatusProgressBar" IsIndeterminate="{Binding IsIndeterminate, Mode=OneWay}" Height="18" Width="120" VerticalAlignment="Center" Background="White" BorderBrush="#FF05438D" />

ViewModel

在DoExecuteGetIpCommand()方法中注意,如果我在内容呈现事件后面的代码中执行相同的操作时可以正常工作,但是在mvvm中,所有代码均同时触发,因此在所有耗时的过程之后更新进度条。

因此,我想在完成最终将IsIndeterminate设置为false之后使用耗时的方法工作时将ProgressBar IsIndeterminate属性设置为true。任何想法,为什么会发生,但是在Content render事件背后的代码中都能正常工作。

public class MainWindowViewModel : INotifyPropertyChanged
{
    public bool _isIndeterminate;
    private string _ipAdrress;
    private bool _errorOccured;        
    public event PropertyChangedEventHandler PropertyChanged;
    GetPublicIP getPublicIP = new GetPublicIP();


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

   /*
    public bool IpIndeterminate
    {
        get { return _isIndeterminate; } 
        set
        {
            _isIndeterminate = value;
            OnPropertyChanged(nameof(IpIndeterminate));
        }
    }
    */

     //OR

    //IsIndeterminate here is problem
    public bool IsIndeterminate => _isIndeterminate;

    public string IpAddress => _ipAdrress;
    public Brush IpForeground => _errorOccured ? new SolidColorBrush(Colors.IndianRed) : new SolidColorBrush(Colors.Black);
    public FontWeight IpFontWeight => _errorOccured ? FontWeights.SemiBold : FontWeights.Normal;


    public ICommand GetIpCommand
    {
        get { return new RelayCommand(param => DoExecuteGetIpCommand()); }
    }        

    private async void DoExecuteGetIpCommand()
    {
        _isIndeterminate = true;
        try
        {                
            _errorOccured = false;
            //_ipAdrress = await MyService.GetIpAddress();
            _ipAdrress = await getPublicIP.GetIPAddressAsync();//time consuming method.
        }
        finally
        {
             //Commented this because progress bar immediately Is indeterminate go false.
            //_isIndeterminate = false;
        }

        if (await getPublicIP.ExceptionOccursAsync() == true)
        {
            _errorOccured = true;
        }
        OnPropertyChanged(nameof(IsIndeterminate));
        OnPropertyChanged(nameof(IpAddress));
        OnPropertyChanged(nameof(IpForeground));
        OnPropertyChanged(nameof(IpFontWeight));            
    }
}    

public class RelayCommand : ICommand
{
    #region Fields

    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    #endregion // Fields

    #region Constructors

    /// <summary>
    /// Creates a new command that can always execute.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute"); //NOTTOTRANS

        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion // Constructors

    #region ICommand Members


    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    #endregion // ICommand Members
}

1 个答案:

答案 0 :(得分:1)

您必须像这样更改您的代码:(如类风虫说)

private async void DoExecuteGetIpCommand()
{
    _isIndeterminate = true;

    //Tell the UI that something changed...
    OnPropertyChanged(nameof(IsIndeterminate));

    try
    {                
        _errorOccured = false;
        _ipAdrress = await getPublicIP.GetIPAddressAsync();//time consuming method.
    }
    finally
    {
        _isIndeterminate = false;
    }

    if (await getPublicIP.ExceptionOccursAsync() == true)
    {
        _errorOccured = true;
    }
    OnPropertyChanged(nameof(IsIndeterminate));
    OnPropertyChanged(nameof(IpAddress));
    OnPropertyChanged(nameof(IpForeground));
    OnPropertyChanged(nameof(IpFontWeight));            
}