Изменение текста кнопки через команды MVVM WPF C#

198
19 апреля 2018, 09:32

Необходимо изменить состояние кнопки ("Старт/Стоп") и запустить одновременно этой кнопкой сервис(в моем случае скриншот с вебкамеры). Пытаюсь сделать таким образом:

public MainWindowViewModel()
    {
        InitializeServices();
        InitializeCommands();
    }
private void ToggleWebServiceExecute()
    {
        //_isRunning = !_isRunning;
        //v_Button_ToggleWebCam.Content = _isRunning ? "Stop" : "Start";
        if (!_faceDetectionService.IsRunning)
        {
            _cameraDetectionService.RunServiceAsync();
        }
        else
        {
            _cameraDetectionService.CancelServiceAsync();
        }
    }
<Button Name="v_Button_ToggleWebCam" Grid.Row="1" Command="{Binding ToggleWebServiceCommand}" 
            VerticalAlignment="Center" Content="{Binding ButtonText}"

Класс ViewModel:

#region ButtonContent
    private ICommand _StartCommand;
    private ICommand _StopCommand;
    private string _buttonText;
    public string ButtonText
    {
        get { return _buttonText ?? (_buttonText = "Start"); }
        set
        {
            // From INotifyPropertyChanged
            //SetField(ref _buttonText, value); 
            NotifyPropertyChanged("ButtonText");
        }
    }
    private ICommand _buttonClickCommand;
    public ICommand ButtonClickCommand
    {
        get { return _buttonClickCommand ?? (_buttonClickCommand = _StartCommand); }
        set
        {
            _buttonClickCommand = value;
            //SetField(ref _buttonClickCommand, value);
            NotifyPropertyChanged("ButtonClickCommand");
        }
    }

    private void Stop()
    {
        ButtonText = "Stop";
        ButtonClickCommand = _StopCommand;
    }
    private void Start()
    {
        ButtonText = "Start";
        ButtonClickCommand = _StartCommand;
    }
    #endregion

Команда на этой же кнопке для запуска сервиса:

 private ICommand _toggleWebServiceCommand;
    public ICommand ToggleWebServiceCommand
    {
        get
        {
            return _toggleWebServiceCommand;
        }
        private set { }
    }

Инициализация команд:

private void InitializeCommands()
    {
        _toggleWebServiceCommand = new DelegateCommand(ToggleWebServiceExecute);
        _StartCommand = new DelegateCommand(Stop);
        _StopCommand = new DelegateCommand(Start);
    }

Класс команды

public class DelegateCommand : ICommand
{
    private readonly Action _command;
    private readonly Func<bool> _canExecute;
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    public DelegateCommand(Action command, Func<bool> canExecute = null)
    {
        if (command == null)
            throw new ArgumentNullException();
        _canExecute = canExecute;
        _command = command;
    }
    public void Execute(object parameter)
    {
        _command();
    }
    public bool CanExecute(object parameter)
    {
        return _canExecute == null || _canExecute();
    }
}
Answer 1

XAML

<Canvas>
    <Button Command="{Binding StartStopCommand, Mode=OneTime}"
            Canvas.Left="183"
            Canvas.Top="222"
            Width="75">
        <Button.Content>
            <TextBlock Text="{Binding ButtonContent}" />
        </Button.Content>
    </Button>
    <ProgressBar Height="20"
                 Minimum="0"
                 Maximum="100"
                 Value="{Binding ProgressShow}"
                 Canvas.Left="77"
                 Canvas.Top="108"
                 Width="299" />
</Canvas>

вьюмодель (немного переделал код под ваш случай пример ответа из вопроса про запуск неблокирующей UI задачи)

public class MainViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    //источник токена отмены
    private CancellationTokenSource _tokenSource;
    //ctor
    public MainViewModel()
    {
    }

    /// <summary>
    /// Надпись на кнопке
    /// </summary>
    private string _ButtonContent;
    public string ButtonContent
    {
        get => _ButtonContent;
        set
        {
            _ButtonContent = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonContent)));
        }
    }
    /// <summary>
    /// Для отображения в ProgressBar
    /// </summary>
    private int _ProgressShow;
    public int ProgressShow
    {
        get => _ProgressShow;
        set
        {
            _ProgressShow = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ProgressShow)));
        }
    }
    /// <summary>
    /// Флаг работы долгой задачи
    /// </summary>
    private bool _IsRunning;
    public bool IsRunning
    {
        get => _IsRunning;
        set
        {
            _IsRunning = value;
            //обновление кнопки
            StartStopCommand.RaiseCanExecuteChanged();
        }
    }

    /// <summary>
    /// Кнопка запуска и останова
    /// </summary>
    private RelayCommand _StartStopCommand;
    public RelayCommand StartStopCommand
    {
        get => _StartStopCommand = _StartStopCommand ?? new RelayCommand(OnStartStop, CanStartStop);
    }
    private bool CanStartStop()
    {
        if (IsRunning)
        {
            ButtonContent = "Стоп";
        }
        else
        {
            ButtonContent = "Старт";
        }
        return true;
    }
    private async void OnStartStop()
    {
        //проверяем а была ли запущена задача
        if (IsRunning)
        {
            //останавливаем задачу
            _tokenSource.Cancel();
            //
            IsRunning = false;
            return;
        }
        //--иначе запускаем задачу
        //кнопки
        IsRunning = true;
        // через него будем оповещать о ходе выполнения задачи
        Progress<int> progress = new Progress<int>(n => ProgressShow = n);
        //готовим токен отмены
        _tokenSource = new CancellationTokenSource();
        CancellationToken cancelToken = _tokenSource.Token;
        try
        {
            // ВНИМАНИЕ! Вот запуск нашего долгого метода
            // обратите внимание на передачу параметров
            // токен отмены мы должны передать и в целевой метод
            // и собственно в метод Run()
            await Task.Run(() => DoIteration(cancelToken, progress), cancelToken);
        }
        catch (OperationCanceledException)
        {
            //случай отмены
            ProgressShow = 0;
        }
        catch (Exception)
        {
            //случай если возникнет какая-то ошибка
            Debug.WriteLine("-->Error");
            ProgressShow = 0;
        }
        finally
        {
            // кнопки
            IsRunning = false;
            // удаляем источник токена отмены
            _tokenSource.Dispose();
        }
    }

    // Это наш долгий метод, который сообщает о ходе своего выполнения
    // и может быть отменен в любой нужный момент
    // обратите внимание на второй параметр IProgress<int> progress
    // здесь должен быть обязательно интерфейс,
    // если случайно нашите Progress<int>, то не найдете Report() 
    private void DoIteration(CancellationToken cancelToken, IProgress<int> progress)
    {
        //создаем экземпляр нашего подсобного класса
        Iteration iteration = new Iteration();
        // типа какая-то полезная работа
        foreach (int number in iteration.StartIterator())
        {
            //отображаем ход работы метода
            progress.Report(number);
            //выбрасываем исключение в случае нажатия на кнопку отмены
            cancelToken.ThrowIfCancellationRequested();
        }
    }
}

Класс команд (писал не сам, пару лет назад взял из одного проекта, и теперь этот класс кочует у меня из проекта в проект)

public class RelayCommand : ICommand
{
    Action _targetExecuteMethod;
    Func<bool> _targetCanExecuteMethod;
    public RelayCommand(Action executeMethod)
    {
        _targetExecuteMethod = executeMethod;
    }
    public RelayCommand(Action executeMethod, Func<bool> canExecuteMethod)
    {
        _targetExecuteMethod = executeMethod;
        _targetCanExecuteMethod = canExecuteMethod;
    }
    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged(this, EventArgs.Empty);
    }
    #region ICommand Members
    bool ICommand.CanExecute(object parameter)
    {
        if (_targetCanExecuteMethod != null)
        {
            return _targetCanExecuteMethod();
        }
        if (_targetExecuteMethod != null)
        {
            return true;
        }
        return false;
    }
    // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
    // Prism commands solve this in their implementation
    public event EventHandler CanExecuteChanged = delegate { };
    void ICommand.Execute(object parameter)
    {
        if (_targetExecuteMethod != null)
        {
            _targetExecuteMethod();
        }
    }
    #endregion
}
public class RelayCommand<T> : ICommand
{
    Action<T> _targetExecuteMethod;
    Func<T, bool> _targetCanExecuteMethod;
    public RelayCommand(Action<T> executeMethod)
    {
        _targetExecuteMethod = executeMethod;
    }
    public RelayCommand(Action<T> executeMethod, Func<T,bool> canExecuteMethod)
    {
        _targetExecuteMethod = executeMethod;
        _targetCanExecuteMethod = canExecuteMethod;
    }
    public void RaiseCanExecuteChanged() 
    {
         CanExecuteChanged(this, EventArgs.Empty); 
    }
    #region ICommand Members
    bool ICommand.CanExecute(object parameter)
    {
        if (_targetCanExecuteMethod != null)
        {
            T tparm = (T)parameter;
            return _targetCanExecuteMethod(tparm);
        }
        if (_targetExecuteMethod != null)
        {
            return true;
        }
        return false;
    }
    // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
    // Prism commands solve this in their implementation
    public event EventHandler CanExecuteChanged = delegate { };
    void ICommand.Execute(object parameter)
    {
        if (_targetExecuteMethod != null)
        {
            _targetExecuteMethod((T)parameter);
        }
    }
    #endregion
}
READ ALSO
Открытие новой вкладки браузера Selenium WebDeiver C#

Открытие новой вкладки браузера Selenium WebDeiver C#

Требуется открыть в браузере две страницыК примеру, программа открывает YouTube

168
С# как прочитать и записать большой exe файл

С# как прочитать и записать большой exe файл

Все мучаюсь над чтением и записью больших exe файлов, нужно чтоб программа читала большой exe файл и меняла в нем некоторые символы после чего...

166
Отображение изображения в picture box

Отображение изображения в picture box

Есть программа на winformsС помощью codefirst создана таблица

153