2016-03-22 17 views
-1

WPF-MVVMパターンを初めて使用しています。私は2つの数字の加算を実行する小さなアプリケーションを書いています。 2つの数字は、ボタンがクリックされたときに追加が行われる間にユーザーによって入力されます。WPF MVVMパターン - コントロールのバインディングが機能しない

問題はResultが3番目のテキストボックスにバインドしていないことです。続き

は私のコード(あなたは追加の問題を発見した場合MVVMに新しいもの、私に知らせてください)です。

のAppクラス - スタートアップ

public partial class App : Application 
{ 
     protected override void OnStartup(StartupEventArgs e) 
     { 
      base.OnStartup(e); 
      MVVM_Math_Calc.Views.Calculator calc = new Views.Calculator(); 
      MVVM_Math_Calc.ViewModels.CalculatorViewModel context = new ViewModels.CalculatorViewModel(); 
      calc.DataContext = context; 
      calc.Show(); 
     } 
    } 

ビュー

<Window x:Class="MVVM_Math_Calc.Views.CalculatorWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Calculator" Height="200" Width="525"> 

    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="1*" /> 
      <ColumnDefinition Width="1*" /> 
      <ColumnDefinition Width="1*" /> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="1*" /> 
      <RowDefinition Height="1*" /> 
      <RowDefinition Height="1*" /> 
     </Grid.RowDefinitions>  
     <Label Content="Number 1" Grid.Column="0" Grid.Row="0" Foreground="Blue" /> 
     <Label Content="Number 1" Grid.Column="1" Grid.Row="0" Foreground="Blue" /> 
     <Label Content="Result"  Grid.Column="2" Grid.Row="0" Foreground="Blue" />  
     <TextBox Name="Num1"  Text="{Binding Number1}" Grid.Column="0" Grid.Row="1" BorderBrush="Gray" /> 
     <TextBox Name="Num2"  Text="{Binding Number2}" Grid.Column="1" Grid.Row="1" BorderBrush="Gray" /> 
     <TextBox Name="Answer"  Text="{Binding Result}"  Grid.Column="2" Grid.Row="1" BorderBrush="Gray" />  
     <Button Content="Addition" Command="{Binding Path=AddNumbersCommand}"  Grid.Column="0" Grid.Row="2" /> 
    </Grid> 
</Window> 

CalculatorViewModel

public class CalculatorViewModel : ViewModelBase 
{ 
     private CalculatorModel calculatorModel; 
     private ICommand  additionCommand; 

     public CalculatorViewModel() 
     { 
      this.CalculatorModel = new CalculatorModel (20, 10); 
     } 

     public CalculatorModel CalculatorModel 
     { 
      get 
      { return calculatorModel; } 
      set 
      { calculatorModel = value; } 
     } 

     public int Result 
     { 
      get { return this.CalculatorModel.Result; } 
      set { this.CalculatorModel.Result = value; } 
     } 

     public int Number1 
     { 
      get { return this.CalculatorModel.Number1; } 
      set { this.CalculatorModel.Number1 = value; } 
     } 

     public int Number2 
     { 
      get { return this.CalculatorModel.Number2; } 
      set { this.CalculatorModel.Number2 = value; } 
     } 

     public ICommand AddNumbersCommand 
     { 
      get 
      { 
       if (additionCommand == null) 
       { 
        additionCommand = new DelegateCommand(param => AddNumbers()); 
       } 

       return additionCommand; 
      } 
     } 

     public void AddNumbers() 
     { 
      Debug.WriteLine ("Addition"); 
      this.CalculatorModel.Result = this.CalculatorModel.Number1 + this.CalculatorModel.Number2; 
      this.Result = this.calculatorModel.Result; 
     } 
    } 

CalculatorModel

public class CalculatorModel : ViewModelBase 
{ 
     private int num1; 
     private int num2; 
     private int result; 

     public CalculatorModel() 
     {} 

     public CalculatorModel (int n1, int n2) 
     { 
      this.Number1 = n1; 
      this.Number2 = n2; 
      this.Result = 0; 
     } 

     public int Number1 
     { 
      get 
      { return num1; } 

      set 
      { 
       if (value != num1) 
       { 
        num1 = value; 
        OnPropertyChanged("Number1"); 
       } 
      } 
     } 

     public int Number2 
     { 
      get 
      { return num2; } 

      set 
      { 
       if (value != num2) 
       { 
        num2 = value; 
        OnPropertyChanged ("Number2"); 
       } 
      } 
     } 

     public int Result 
     { 
      get 
      { return result; } 

      set 
      { 
       if (value != result) 
       { 
        result = value; 
        OnPropertyChanged ("Result"); 
       } 
      } 
     } 
    } 

ViewModelBase

public class ViewModelBase : INotifyPropertyChanged 
    { 
     // event handler 
     public event PropertyChangedEventHandler PropertyChanged; 

     public void OnPropertyChanged (string propertyName) 
     { 
      this.VerifyPropertyName (propertyName); 
      PropertyChangedEventHandler handler = this.PropertyChanged; 

      if (handler != null) 
      { 
       handler (this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     public virtual void VerifyPropertyName(string propertyName) 
     { 
      // Verify that the property name matches a real, 
      // public, instance property on this object. 
      if (TypeDescriptor.GetProperties(this)[propertyName] == null) 
      { 
       string msg = "Invalid property name: " + propertyName; 
       throw new Exception ("Error"); 
      } 
     } 
    } 

DelegateCommand

public class DelegateCommand : ICommand 
{ 
     readonly Action<object>  _execute; 
     readonly Predicate<object> _canExecute; 

     public DelegateCommand (Action<object> execute) : this (execute, null) 
     {} 

     /// <param name="canExecute">The execution status logic.</param> 
     public DelegateCommand (Action<object> execute, Predicate<object> canExecute) 
     { 
      if (execute == null) 
       throw new ArgumentNullException("execute"); 

      _execute = execute; 
      _canExecute = canExecute; 
     } 

     [DebuggerStepThrough] 
     public bool CanExecute(object parameters) 
     { 
      return _canExecute == null ? true : _canExecute(parameters); 
     } 

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

     public void Execute(object parameters) 
     { 
      Debug.WriteLine("Execute"); 
      _execute (parameters); 
     } 
    } 
+0

viewmodelでこれらのプロパティを追加のプロパティとして公開する代わりに、CalculatorModel.Number1、CalculatorModel.Number2、CalculatorModel.Resultにバインドしてみてください。また、viewmodelのCalculatorModelプロパティのPropertyChangedイベントを発生させます。 –

答えて

2

あなたは値が変更されたとき、プロパティ変更通知を上げない、CalculatorViewModel.Resultに結合されています。 WPFバインディングは通知を使用して、更新する必要があることを認識します。

2種類の溶液:

  1. バインドCalculatorViewModel.Result

    <TextBox Name="Answer" Text="{Binding CalculatorModel.Result}" .. /> 
    
  2. に代わりのCalculatorModel.Resultしたり、ViewModel.ResultたびModel.Result変更のPropertyChangedイベントを発生させます。例えば

    :しないように十分な理由がない限り

    public CalculatorModel CalculatorModel 
    { 
        get { return calculatorModel; } 
        set 
        { 
         // remove old event if necessary 
         if (calculatorModel != null) 
          calculatorModel.PropertyChanged -= CalculatorModel_PropertyChanged; 
    
         calculatorModel = value; 
    
         // attach a propertyChanged event to re-raise for ViewModel 
         if (calculatorModel != null) 
          calculatorModel.PropertyChanged += CalculatorModel_PropertyChanged; 
        } 
    } 
    
    private void CalculatorModel_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
        if (e.PropertyName == "Result") 
         OnPropertyChanged("Result"); 
    } 
    

一般的に、私は#1を使用します。

+0

レイチェル、そうです。モデルへのバインドがトリックでした。私はViewModelからプロパティを削除してしまいました。 –

+0

レイチェル、私はMVVMを初めて使っているので、 "DelegateCommand"が特にCommandManagerの仕組みにはあまり明確ではありません。このクラスはMVVMの標準として使用されるので、このクラスを少し説明できますか。 –

+0

最後に、オブジェクトコレクションにバインドする方法を教えてください。私はObservableCollection がプロパティとして公開されているのを見ました。これは正しい方法ですか? –

関連する問題