0

看法:

使用 WPF(MVVM) 玩一个基本的计算器。我有 1 个文本框用于第一个数字,1 个文本框用于第二个数字,1 个文本块用于结果和 1 个按钮来执行 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,但仍然无法正常工作。

4

2 回答 2

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)视图模型。在这里,你RelayCommand真的不需要任何论据。但是您需要将操作数的值存储在您的 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");
        }
    }

等等

于 2012-08-15T15:27:22.107 回答
0

谢谢大家,尤其是@Vlad。Result只是一个小错误,你已经在上两次声明了该属性class CalcViewModel : DependencyObject

它现在工作正常:)

于 2012-08-16T15:16:15.543 回答