获取文本框值的WPF MVVM按钮命令

时间:2015-05-12 16:00:22

标签: c# wpf xaml mvvm

我很难理解按钮命令的工作原理。我有类似的东西

{Binding TxtBox}从模型中获取价值,让我们说它是“aaa”。我想点击按钮,该值应显示在第二个文本框中({Binding TxtBox2})。

这是我的xaml:

<TextBox Text="{Binding TxtBox, Source={StaticResource viewModel}}" />
<TextBox Text="{Binding TxtBox2, Source={StaticResource viewModel}}" />
<Button Command="{Binding ClickCommand}"/>

这是我的ViewModel:

public class CommandHandler : ICommand
{
    private Action _action;
    private bool _canExecute;
    public CommandHandler(Action action, bool canExecute)
    {
        _action = action;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute;
    }

    public event EventHandler CanExecuteChanged;

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

我真的需要这个CommandHandler课吗?我从网上复制了代码。

public string TxtBox
{
    get { return Model.TxtBoxValue; }
    set { Model.TxtBoxValue = value; }
}
public string TxtBox2 { get; set; }

private ICommand _clickCommand;
public ICommand ClickCommand
{
    get
    {
        return _clickCommand ?? (_clickCommand = new CommandHandler(() => MyAction(), _canExecute)); // I believe that when the button is clicked MyAction() is triggered, right?

    }

}
private bool _canExecute = true;
public void MyAction()
{
    this.TxtBox2 = this.TxtBox; // should something like this work? Because right now it doesn't
}

2 个答案:

答案 0 :(得分:0)

第二个文本框的绑定永远不会被通知它的绑定属性被更改。设置this.TxtBox2时,应该触发该属性的propertychanged事件,以便更新绑定。 See think link for everything on bindings

我不知道你是否使用prism作为mvvm框架,但是它附带了DelegateCommand类。我认为.net框架中没有简单/轻量级的实现。 See this link for the mvvm framework and the delegate command

答案 1 :(得分:0)

View通过PropertyChanged事件对绑定更改做出反应,而事件没有。有任何绑定到View的工具实现INotifyPropertyChanged,然后在道具更改时触发事件,并且您已经设置了绑定工作(单向或双向)。

将您的模型更改为这样,它应该适合您。


public class MyViewModel : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged = null;

    protected virtual void RaisePropertyChanged(string propName)
    {
        if(PropertyChanged != null)
        {
            Task.Run(() => PropertyChanged(this, new PropertyChangedEventArgs(propName)));
        }
    }

    #endregion

    public string TxtBox
    {
        get { return Model.TxtBoxValue; }
        set
        {
            Model.TxtBoxValue = value;
            RaisePropertyChanged("TxtBox");
        }
    }

    // presuming TxtBox2Value is in Model...else use a field
    public string TxtBox2
    {
        get { return Model.TxtBox2Value; }
        set
        {
            Model.TxtBox2Value = value;
            RaisePropertyChanged("TxtBox2");
        }
    }

    private ICommand _clickCommand;
    public ICommand ClickCommand
    {
        get
        {
            return _clickCommand ?? (_clickCommand = new CommandHandler(() => MyAction(), _canExecute)); // I believe that when the button is clicked MyAction() is triggered, right?

        }

    }
    private bool _canExecute = true;
    public void MyAction()
    {
        this.TxtBox2 = this.TxtBox; // should something like this work? Because right now it doesn't
    }
}

IMO - 最好让你的Model实现INotifyPropertyChanged,然后直接绑定到它而不是将它包装在ViewModel中。如果Model:INotifyPropertyChanged,那么您的ViewModel现在看起来像这样:


public class MyViewModel
{

    // fire prop changed event here if this model will be swapped out after the ctor...otherwise don't worry about it
    public Model Model { get; set; }

    private ICommand _clickCommand;
    public ICommand ClickCommand
    {
        get
        {
            return _clickCommand ?? (_clickCommand = new CommandHandler(() => MyAction(), _canExecute)); 

        }

    }
    private bool _canExecute = true;
    public void MyAction()
    {
        Model = new Model();

        Model.TxtBox2 = "Some new value"; 
    }
}

...并且您的xaml更改为:

<TextBox Text="{Binding Model.TxtBox, Source={StaticResource viewModel}}" />
<TextBox Text="{Binding Model.TxtBox2, Source={StaticResource viewModel}}" />
<Button Command="{Binding ClickCommand}"/>