0

意見:

WPF(MVVM)を使用して基本的な計算機で遊ぶ。最初の数値に1つのTextBox、2番目の数値に1つのTextBox、結果に1つのTextBlock、AddCommandを実行して結果を返すための1つのボタンがあります。これらのコントロールを適切なデータにバインドするための適切な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;
    }
}

ViewModel:

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;
        }
    }

ViewModel:

 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)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、.NET4.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に感謝します。小さな欠点が1つだけありますが、プロパティをResult2回宣言しましたclass CalcViewModel : DependencyObject

今は問題なく動作します:)

于 2012-08-16T15:16:15.543 に答える