WPF - MVVM 绑定
WPF - MVVM Bindings
我的应用程序有问题,尤其是 WPF MVVM 中的绑定。
我创建了模型、视图模型和视图,这是我的代码的一部分(只有这与我的问题有关)当我单击 nemed 按钮时:PointUp 我想查看 Team1 点数。谁能告诉我我做错了什么?
查看
<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; }
}
}
'
视图模型
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(); }
}
}
问题在这里:
public int TeamPoints
{
get { return TeamPoints; } //should be Team1.TeamPoints
set { TeamPoints = value; OnPropertyChanged("TeamPoints"); } //should be Team1.TeamPoints
}
在 TeamPoints
属性 中 ViewModel
中 return 并设置与 ViewModel
相同的 属性 TeamPoints
但是您应该从 Model
(Team1
) 开始设置。您应该 return 并设置 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");
}
我估计是因为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));
}
}
}
您必须像这样更新您的绑定。
<Label x:Name="PointsTeam1_label" Content="{Binding TeamPoints, UpdateSourceTrigger=PropertyChanged }"/>
当您绑定到 Team1.TeamPoints 时,您将不会从您的 TeamPoints 属性.
中的 OnPropertyChanged 获得通知
我的应用程序有问题,尤其是 WPF MVVM 中的绑定。 我创建了模型、视图模型和视图,这是我的代码的一部分(只有这与我的问题有关)当我单击 nemed 按钮时:PointUp 我想查看 Team1 点数。谁能告诉我我做错了什么?
查看
<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; }
}
}
'
视图模型
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(); }
}
}
问题在这里:
public int TeamPoints
{
get { return TeamPoints; } //should be Team1.TeamPoints
set { TeamPoints = value; OnPropertyChanged("TeamPoints"); } //should be Team1.TeamPoints
}
在 TeamPoints
属性 中 ViewModel
中 return 并设置与 ViewModel
相同的 属性 TeamPoints
但是您应该从 Model
(Team1
) 开始设置。您应该 return 并设置 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");
}
我估计是因为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));
}
}
}
您必须像这样更新您的绑定。
<Label x:Name="PointsTeam1_label" Content="{Binding TeamPoints, UpdateSourceTrigger=PropertyChanged }"/>
当您绑定到 Team1.TeamPoints 时,您将不会从您的 TeamPoints 属性.
中的 OnPropertyChanged 获得通知