RelayCommand Params&捆绑

时间:2012-08-15 15:15:57

标签: wpf mvvm binding relaycommand

查看:

使用WPF(MVVM)播放基本计算器。 我有1个TextBox用于第一个num,1个TextBox用于第二个num,1个TextBlock用于结果,1个Button用于执行AddCommand并返回结果。 什么是将这些控件绑定到正确数据的正确XAML语法。

型号:

public class Operation : INotifyPropertyChanged
{
    private double _result;
    public Operation()
    {
        _result = 0;
    }

    public double Result
    {
        get { return _result; }
        set
        {
            if (value != _result)
            {
                _result = value;
                RaisePropertyChanged("Result");
            }
        }
    }

    public double DoAdd(double first, double second)
    {
        _result = first + second;
        return _result;
    }
}

视图模型:

public class CalcViewModel
{
    private Operation _operation;
    public RelayCommand AddCommand { get; set; }

    public CalcViewModel()
    {
        _operation = new Operation();

        // This is not correct, how to define the AddCommand here so it takes two params
        // The first and second nums to work with.
        AddCommand = new RelayCommand(first, second => ExecuteAddCommand(first, second));
    }

    private void ExecuteAddCommand(double first, double second)
    {

        // How to bind this returned double to the TextBlock in View
        _oepration.DoAdd(first, second);
    }
}

根据Vlad的要求编辑新版代码

型号:

public class Operation
    {
        private double _result;

        public Operation()
        {
            _result = 0;
        }

        public double Result
        {
            get { return _result; }
        }

        public void PerformAdd(double leftNum, double rightNum)
        {
            _result = leftNum + rightNum;
        }
    }

视图模型:

 public class CalcViewModel
    {
        private Operation _operation;
        public double LeftNumber { get; set; }
        public double RightNumber { get; set; }
        public double Result { get; set; }

        public RelayCommand AddCommand { get; set; }

        public CalcViewModel()
        {
            AddCommand = new RelayCommand(a => ExecuteAddCommand());
            _operation = new Operation();
        }

        private void ExecuteAddCommand()
        {
            _operation.PerformAdd(LeftNumber, RightNumber);
            Result = _operation.Result;
        }

查看XAML:

<TextBox Text="{Binding LeftNumber}" />
<TextBox Text="{Binding RightNumber}" />
<TextBox Text="{Binding Result}" />
<Button Content="Add" Command="{Binding AddCommand}" />

查看代码背后:

public partial class CalcUserControl : UserControl
{
    CalcViewModel vm;

    public CalcUserControl()
    {
        InitializeComponent();
        vm = new CalcViewModel();
        this.DataContext = vm;
    }
}

我尝试了所有绑定模式而没有任何结果。我在这里有一个额外的问题,在这种情况下什么是默认的绑定模式?

我甚至认为它与计算的数据类型有关,所以我从double变为int,但仍无法正常工作。

2 个答案:

答案 0 :(得分:0)

好吧,让我们看看可以做些什么。

1)模型。该模型不需要任何花哨的东西。我会保持简单,让它只返回值,而不是使用NotifyPropertyChanged。毕竟,这是一个模型。

public class BinaryOperation
{
    double _l, _r, _result = 0.0;
    public Operation(double l, double r)
    {
        _l = l; _r = r;
    }

    public double Result
    {
        get { return _result; }
    }

    public PerformAdd()
    {
        _result = _l + _r;
    }
}

2)ViewModel。在这里,您的RelayCommand并不需要任何参数。但是您需要在VM中存储操作数的值,以便您的视图可以绑定到它们,而不是在命令中发送它们。请记住,业务逻辑不属于视图,视图只是盲目地绑定到VM!因此,您需要在VM中使用3个DP(左加数,右加数,结果)。

3)当命令到达时,您只需从VM获取加数,请模型执行操作,检索结果并将其分配给VM的结果DP。 (现在,您的模型操作速度很快,因此您不需要以异步方式执行此操作。但可能在将来......)

4)查看。您需要将Window / UserControl绑定到VM的属性。 它将变得如此简单:

<TextBox Text="{Binding LeftAddend}"/>
<TextBox Text="{Binding RightAddend}"/>
<TextBox Text="{Binding Result}"/>
<Button Command="{Binding AddCommand}">Add</Button>

(不要忘记将DataContext设置为正确。)

编辑:
VM类必须是依赖对象!并且属性应该定义为依赖属性。像这样:

public class CalcViewModel : DependencyObject
{
    private Operation _operation;

    public double LeftNumber
    {
        get { return (double)GetValue(LeftNumberProperty); }
        set { SetValue(LeftNumberProperty, value); }
    }

    public static readonly DependencyProperty LeftNumberProperty = 
        DependencyProperty.Register("LeftNumber", typeof(double), typeof(CalcViewModel));

    public double RightNumber
    {
        get { return (double)GetValue(RightNumberProperty); }
        set { SetValue(RightNumberProperty, value); }
    }

    public static readonly DependencyProperty RightNumberProperty = 
        DependencyProperty.Register("RightNumber", typeof(double), typeof(CalcViewModel));

    public double Result
    {
        get { return (double)GetValue(ResultProperty); }
        set { SetValue(ResultProperty, value); }
    }

    public static readonly DependencyProperty ResultProperty = 
        DependencyProperty.Register("Result", typeof(double), typeof(CalcViewModel));

    public RelayCommand AddCommand { get; set; }

    public CalcViewModel()
    {
        AddCommand = new RelayCommand(a => ExecuteAddCommand());
        _operation = new Operation();
    }

    private void ExecuteAddCommand()
    {
        _operation.PerformAdd(LeftNumber, RightNumber);
        Result = _operation.Result;
    }
}

或者,如果您想使用INotifyPropertyChanged,并且您正在使用.NET 4.5

public class CalcViewModel : INotifyPropertyChanged
{
    private Operation _operation;

    public event PropertyChangedEventHandler PropertyChanged;

    void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    double _leftNumber;
    public double LeftNumber
    {
        get { return _leftNumber; }
        set
        {
            if (value == _leftNumber) return;
            _leftNumber = value;
            NotifyPropertyChanged();
        }
    }

    double _rightNumber;
    public double RightNumber
    {
        get { return _rightNumber; }
        set
        {
            if (value == _rightNumber) return;
            _rightNumber = value;
            NotifyPropertyChanged();
        }
    }

    double _result;
    public double Result
    {
        get { return _result; }
        set
        {
            if (value == _result) return;
            _result = value;
            NotifyPropertyChanged();
        }
    }

    public RelayCommand AddCommand { get; set; }

    public CalcViewModel()
    {
        AddCommand = new RelayCommand(a => ExecuteAddCommand());
        _operation = new Operation();
    }

    private void ExecuteAddCommand()
    {
        _operation.PerformAdd(LeftNumber, RightNumber);
        Result = _operation.Result;
    }
}

与旧的.NET版本相同:

    void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    double _leftNumber;
    public double LeftNumber
    {
        get { return _leftNumber; }
        set
        {
            if (value == _leftNumber) return;
            _leftNumber = value;
            NotifyPropertyChanged("LeftNumber");
        }
    }

答案 1 :(得分:0)

谢谢大家,特别是@Vlad。只是一个小小的错误,你已经在Result两次声明属性class CalcViewModel : DependencyObject

现在工作正常:)