WPF MVVM - простая кнопка привязки с текстовым полем (Icommand) - PullRequest
0 голосов
/ 28 сентября 2018

Я пытаюсь сделать следующее: когда текстовое поле содержит значение «123», оно должно активировать кнопку и позволить мне щелкнуть ее.

Изображение решения & Просмотр изображения

Я не могу найти способ вызвать команду кнопки (класс SpecialCommand.cs), основанный на моих параметрах кнопки.Не могли бы вы поддержать, где я неправильно получаю этот шаблон MVVM?

WPF View [MainWindow.xaml]:

<Window.Resources>
    <ViewModel:MainWindowVM x:Key="WindowVm"></ViewModel:MainWindowVM>
</Window.Resources>

<Grid>
    <StackPanel>
        <TextBox x:Name="textBox" Margin="0, 5" Text="123"/>
        <Button Content="Click me!" Margin="0, 5" Command="{Binding SpecialCommand, Source={StaticResource WindowVm}}" CommandParameter="{Binding Text, ElementName=textBox, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
    </StackPanel>
</Grid>

ViewModel [MainWindowVM.cs]:

public class MainWindowVM
{
    private SpecialCommand _specialCommand;

    public SpecialCommand SpecialCommand { get => _specialCommand; set => _specialCommand = value; }

    public MainWindowVM()
    {
        _specialCommand = new SpecialCommand();
    }

}

Command [SpecialCommand.cs]

public class SpecialCommand : ICommand
{
    public bool CanExecute(object parameter)
    {
        if (parameter != null && (parameter as string) == "123")
            return true;

        return false;
    }

    public void Execute(object parameter)
    {
        MessageBox.Show("Button Pressed!");
    }

    public event EventHandler CanExecuteChanged;
}

Возможно, я ошибаюсь, поскольку кнопка и текстовое поле находятся в представлении. Мне не нужно добавлять или изменять какие-либо методы вмоя реализация SpecialCommand.Они должны иметь возможность видеть, когда свойство изменяется.Как и CanExecuteChanged () ниже, эта команда многократно вызывается и кажется излишней для этой небольшой задачи.

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

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Вам нужен способ сообщить команде, что она должна проверить, является ли она CanExecute.Это делается путем запуска события CanExecuteChanged.Она сообщает кнопке запросить свойство CanExecute.

Чтобы это работало, я бы добавил текстовое свойство к вашей модели представления и привязал к нему текстовое поле.

В SpecialCommandдобавьте метод:

public void TriggerCanExecuteChanged()
{
    CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}

В классе MainWindowVM добавьте свойство:

private string _text;
public string Text
{
    get { return _text; }
    set {
        if (value != _text) {
            _text = value;
            _specialCommand.TriggerCanExecuteChanged();
        }
    }
}

Просмотр модели для реализации INotifyPropertyChanged (см. комментарии):

public class MainWindowVM : INotifyPropertyChanged
{
    public SpecialCommand SpecialCommand { get; set; } = new SpecialCommand();

    private string _text;
    public string Text
    {
        get { return _text; }
        set {
            if (value != _text) {
                _text = value;
                OnPropertyChanged(nameof(Text));
                SpecialCommand.TriggerCanExecuteChanged();
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
0 голосов
/ 28 сентября 2018

Нет необходимости делать его более сложным, чем нужно.

public class MainWindowVM
{
    private string m_OneTwoThree;
    public string OneTwoThree{
        get { return OneTwoThree; }
        set {
            if (m_OneTwoThree != value){
                m_OneTwoThree = value;
                NotifyPropertyChanged(nameof(OneTwoThree)); //if you need this let me know
            }
        }
    }       

    public MainWindowVM()
    {

    }


    public ICommand RandomCommand { get { return new RelayCommand(OnRandom, IsOneTwoThree); } }


    private void OnRandom()
    {
        //do stuff
    }

    private bool IsOneTwoThree(){
        if (OneTwoThree == "123"){
            return true;
        }
        return false;
    }
}

Вам также придется обновить xaml Не думаю, что он сможет найти«OneTwoThree», так что вам придется связывать его самостоятельно, как обычно.

<StackPanel>
    <TextBox x:Name="textBox" Margin="0, 5" Text="{Binding OneTwoThree}"/>
    <Button Content="Click me!" Margin="0, 5" Command="{Binding RandomCommand, Source={StaticResource WindowVm}}"/>
</StackPanel>

Если у вас есть какие-либо вопросы, просто задавайте.

Это моя RelayCommand: используйте RelayCommand («вещь для выполнения», «если функция возвращает true, вы можете выполнить»);

public class RelayCommand : ICommand
{
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    private Action methodToExecute;
    private Func<bool> canExecuteEvaluator;
    public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
    {
        this.methodToExecute = methodToExecute;
        this.canExecuteEvaluator = canExecuteEvaluator;
    }
    public RelayCommand(Action methodToExecute)
        : this(methodToExecute, null)
    {
    }
    public bool CanExecute(object parameter)
    {
        if (this.canExecuteEvaluator == null) {
            return true;
        }
        else {
            bool result = this.canExecuteEvaluator.Invoke();
            return result;
        }
    }
    public void Execute(object parameter)
    {
        this.methodToExecute.Invoke();
    }
}
...