2017-03-03 9 views
1

私のアプリケーションには、特にWPF MVVMのバインディングで問題があります。 Model、ViewModel、Viewを作成しました。これは私のコードの一部です(これは私の問題に関連しています)。ボタンをクリックすると、PointUpがTeam1ポイントの量を表示します。誰かが私が間違っていることを教えてもらえますか?WPF - MVVMバインディング

ビュー

<Window x:Class="Tabu.Game 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:Tabu" 
     xmlns:vm="clr-namespace:Tabu.ViewModel" 
     mc:Ignorable="d" 
     Title="Game" Height="600" Width="900" Background="Beige"> 
    <Window.DataContext> 
     <vm:TeamStatistic /> 
    </Window.DataContext> 
    <Grid> 
     <Button x:Name="PointUp" Command="{Binding AddPoints }" Content="+"/> 
     <Label x:Name="PointsTeam1_label" Content="{Binding Team1.TeamPoints, UpdateSourceTrigger=PropertyChanged }"/> 
</Grid> 

モデル

'

namespace Tabu.Model 
{ 
    public class Team 
    { 
     public bool IsTeamActive { get; set; } 
     public int TeamMiss { get; set; } 
     public int TeamPoints { get; set; } 
     public int TeamMistake { get; set; } 
    } 
}
'

のViewModel

namespace Tabu.ViewModel 
{ 
    class TeamStatistic : INotifyPropertyChanged 

    { 
     public Team Team1 = new Team(); 

     public int TeamPoints 
     { 
      get { return TeamPoints; } 
      set { TeamPoints = value; OnPropertyChanged("TeamPoints"); } 
     } 

     public ICommand AddPoints 
     { 
      get { return new RelayCommand(() => Add_Points()); } 
     } 

     public void Add_Points() 
     { 
      Team1.TeamPoints++; 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     private void OnPropertyChanged(params string[] propsName) 
     { 
      if (PropertyChanged!=null) 
      { 
       foreach(string propName in propsName) 
       PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
      } 
     } 
    } 

public class RelayCommand : ICommand 
    { 
     private readonly Func<bool> canExecute; 
     private readonly Action execute; 

     public RelayCommand(Action execute) 
      : this(execute, null) { } 

     public RelayCommand(Action execute, Func<bool> canExecute) 
     { 
      if (execute == null) throw new ArgumentNullException("execute"); 
      this.execute = execute; 
      this.canExecute = canExecute; 
     } 

     public event EventHandler CanExecuteChanged 
     { 
      add { if (this.canExecute != null) CommandManager.RequerySuggested += value; } 
      remove { if (this.canExecute != null) CommandManager.RequerySuggested -= value; } 
     } 

     public Boolean CanExecute(object parameter) { return this.canExecute == null ? true : this.canExecute(); } 
     public void Execute(object parameter) { this.execute(); } 
    } 
} 

答えて

1

はあなたがこのようにバインディング更新する必要があります。

<Label x:Name="PointsTeam1_label" Content="{Binding TeamPoints, UpdateSourceTrigger=PropertyChanged }"/> 

あなたがあなたのTeamPointsプロパティ内にあるOnPropertyChangedをからの通知を取得することはありませんTeam1.TeamPointsに特異的に結合します。

+0

はい、その真実、私の間違い:それは動作しますが、最初の時点では、ポイントの量はまだ同じexual 0です。バインディングは、リフレッシュしません – Arkady

+0

ああ、問題が表示されます。 AddTeamPointsメソッドでTeam1.Teampointsを更新すると、NotifyPropertyChangedは再度トリガーされません。 書き込み時にOnPropertyChanged( "TeamPoints"); Team1.TeamPoints ++の後;それは大丈夫でしょう。 –

+0

ありがとう!私はそれを気付かなかった。 – Arkady

2

問題はここにある:

public int TeamPoints 
{ 
    get { return TeamPoints; } //should be Team1.TeamPoints 
    set { TeamPoints = value; OnPropertyChanged("TeamPoints"); } //should be Team1.TeamPoints 
} 
であなたの TeamPoints財産インサイド

あなたは戻ってViewModelから同じプロパティTeamPointsを設定していますがModelTeam1)から設定する必要があります。返品してTeam1.TeamPointsを設定してください。

public int TeamPoints 
{ 
    get { return Team1.TeamPoints; } 
    set { Team1.TeamPoints = value; OnPropertyChanged("TeamPoints"); } 
} 

そしてAdd_Points()

public void Add_Points() 
{ 
    Team1.TeamPoints++; 
    OnPropertyChanged("TeamPoints"); 
} 
+0

ありがとう、しかし、私はまだ私のビュー内のポイントを参照してください。 – Arkady

0

私はそれが理由AddPoints(コマンドバインディング)である数えます。このコマンドはバインドされているため、バインディングを破る可能性があるたびにRelayCommand &のインスタンスを作成しています。&

CommandBindingsのより良い代替案は、プロパティを宣言し、それらをビューモデルのコンストラクタで初期化することです。

例:

namespace Tabu.ViewModel 
{ 
    class TeamStatistic : INotifyPropertyChanged 

    { 
    public Team Team1 = new Team(); 

    public int TeamPoints 
    { 
     get { return Team1.TeamPoints; } 
     set { Team1.TeamPoints = value; OnPropertyChanged("TeamPoints"); } 
    } 

    private ICommand _AddPoints; 

    public ICommand AddPoints 
    { 
     get { return _AddPoints; } 
     set { _AddPoints = value; } 
    } 

    public void Add_Points() 
    { 
     Team1.TeamPoints++; 
    } 

    public TeamStatistic() 
    { 
     _AddPoinss = new RelayCommand(Add_Points); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void OnPropertyChanged(params string[] propsName) 
    { 
     if (PropertyChanged!=null) 
     { 
      foreach(string propName in propsName) 
      PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
     } 
    } 
} 
+0

P.S:RelayCommandクラスは同じままです。 – Ankit