【问题标题】:MVVM executes all codes at once in Execute CommandMVVM 在 Execute Command 中一次执行所有代码
【发布时间】:2018-12-17 16:47:15
【问题描述】:

我正在使用我之前的question 中提供的 MVVM 解决方案

XAML

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

视图模型

请注意在 DoExecuteGetIpCommand() 方法中,如果我在内容渲染事件后面的代码中执行相同的操作,但在 mvvm 中所有代码同时触发,因此在所有耗时过程之后进度条会更新。

所以我想将 ProgressBar IsIndeterminate 属性设置为 true,而耗时的方法在完成后将 IsIndeterminate 设置为 false。对此有任何想法以及为什么会发生但在内容呈现事件背后的代码中工作正常。

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
}

【问题讨论】:

  • 那是因为您仅在方法结束时才通知属性更改。不是很明显吗?
  • @dymanoid 我还使用了第二种方法,它是注释代码,因为 OR 部分做同样的事情,即使属性更改不在方法中
  • 如果唯一的区别是注释代码,那么即使在这种情况下,您也只会在方法结束时通知属性更改。请仔细阅读属性、字段和INotifyPropertyChanged 实现。
  • @dymanoid 好的,我明白了,所以我需要执行/重复 OnNotifyPropertyChange(nameof(xyz));每一次 ?例如在设置 IsIndeterminate = true 后开启;另一个是假的??对吗

标签: c# wpf mvvm progress-bar


【解决方案1】:

您必须像这样更改您的代码:(正如 dymanoid 所说)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    相关资源
    最近更新 更多