MVVM 混淆试图让 INotifyProprerty 更改以使用 XAML 更新
MVVM confusion trying to get INotifyProprerty change to work with XAML updates
我搜索并阅读了大量类似的话题,还观看了一些视频,但我 运行 遇到了一些问题,我认为这归结为一些误解。我正在使用 MVVM 和 UWP 开发来学习 70-357 考试。
我的目标:在我的 XAML 页面中按下一个按钮,让它更改我的 ViewModel 中对象的 属性,然后将该值反映在我的 XAML 中的数据绑定中] 看法。
在我的项目中,我有以下内容:
主页XAML
<StackPanel Name="HPStack" Margin="0,0,10,0">
<Button Name="HPIncrease" Click="{x:Bind CharacterViewModel.HPIncrease_Click}" Content="+" HorizontalAlignment="Center"/>
<TextBlock Name="HPTB" Text="{x:Bind CharacterViewModel.myCharacter.CurrentHP}" Margin="0,0,5,0" HorizontalAlignment="Center"/>
<Button Name="HPDecrease" Click="{x:Bind CharacterViewModel.HPDecrease_Click}" Content="-" HorizontalAlignment="Center"/>
</StackPanel>
主页 C#
public CharacterDetailsViewModel CharacterViewModel;
public MainPage()
{
this.InitializeComponent();
CharacterViewModel = new CharacterDetailsViewModel();
}
角色视图模型(大部分代码来自我看到的解释
public class CharacterDetailsViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
//App data
private Character _myCharacter;
public Character myCharacter
{
set
{
_myCharacter = value;
OnPropertyChanged();
}
get { return _myCharacter; }
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
//Constructors
public CharacterDetailsViewModel()
{
_myCharacter = new Character(12, 12, 12, 12, 12, 12);
}
//buttons
public void HPIncrease_Click(object sender, RoutedEventArgs e)
{
//TODO probably fix this
myCharacter.CurrentHP++;
}
public void HPDecrease_Click(object sender, RoutedEventArgs e)
{
myCharacter.CurrentHP--;
}
}
Character Model(去掉了很多不相关的属性)
public class Character
{
public int TotalHP { get; set; } //TODO not public
public int CurrentHP {get;set;} //TODO check vs total HP and 0
//constructor for creating a new character with provided stats
public Character (int strength, int dexterity, int constitution, int intelligence, int wisdom, int charisma)
{
this.TotalHP = 50;
this.CurrentHP = 45;
}
}
- 我的所有属性最初似乎都能正确找到
- 当我单击按钮更改 CurrentHP 时,我没有在 XAML
上看到这反映出来
- 我知道 prism 和 template 10 存在。我不想使用它们,因为我正在编写此代码以更好地理解这些东西以准备认证。将来我可能会利用它们,但我想弄清楚在这种情况下我做错了什么。
到目前为止,我的理解是我应该只将 INotfyPropertyChanged 放在 ViewModel 上,它可以处理自定义对象(在本例中为 Character)内的任何 属性 已更改的警报。
我错了吗? 我的角色 class 是否需要 INotifyPropertyChanged 才能正确提醒 XAML 这些更改?
感谢您在这里提供任何意见。
在您的视图模型中,您已经实现了 INotifyPropertyChanged
,因此如果您将 Character
设置为一个新对象,事件将被执行并且 WPF 将更新。
问题是当 Character
的 属性 改变时,没有发送通知事件,WPF 不知道刷新它的值。
您可以在 Character
中实现接口,在视图模型上触发 INotifyPropertyChanged
,或者将 Character
的 public 属性更改为依赖属性.
有两件事会阻止您的 UI 更新:
- 您的
Character
未实现 INotifyPropertyChanged,因此 UI 不会收到有关更改的通知。实现它并在适当的设置器中调用 OnPropertyChanged,否则你将不得不在 myCharacter
上调用 OnPropertyChanged,这应该会刷新整个 字符,但第一种方法更好,
- 第二个重要的事情是它也不会工作,除非你让你绑定 OneWay -
x:Bind
默认为 OneTime,所以你应该更正:
<TextBlock Name="HPTB" Text="{x:Bind CharacterViewModel.myCharacter.CurrentHP, Mode="OneWay"}"...
我搜索并阅读了大量类似的话题,还观看了一些视频,但我 运行 遇到了一些问题,我认为这归结为一些误解。我正在使用 MVVM 和 UWP 开发来学习 70-357 考试。
我的目标:在我的 XAML 页面中按下一个按钮,让它更改我的 ViewModel 中对象的 属性,然后将该值反映在我的 XAML 中的数据绑定中] 看法。
在我的项目中,我有以下内容:
主页XAML
<StackPanel Name="HPStack" Margin="0,0,10,0">
<Button Name="HPIncrease" Click="{x:Bind CharacterViewModel.HPIncrease_Click}" Content="+" HorizontalAlignment="Center"/>
<TextBlock Name="HPTB" Text="{x:Bind CharacterViewModel.myCharacter.CurrentHP}" Margin="0,0,5,0" HorizontalAlignment="Center"/>
<Button Name="HPDecrease" Click="{x:Bind CharacterViewModel.HPDecrease_Click}" Content="-" HorizontalAlignment="Center"/>
</StackPanel>
主页 C#
public CharacterDetailsViewModel CharacterViewModel;
public MainPage()
{
this.InitializeComponent();
CharacterViewModel = new CharacterDetailsViewModel();
}
角色视图模型(大部分代码来自我看到的解释
public class CharacterDetailsViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
//App data
private Character _myCharacter;
public Character myCharacter
{
set
{
_myCharacter = value;
OnPropertyChanged();
}
get { return _myCharacter; }
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
//Constructors
public CharacterDetailsViewModel()
{
_myCharacter = new Character(12, 12, 12, 12, 12, 12);
}
//buttons
public void HPIncrease_Click(object sender, RoutedEventArgs e)
{
//TODO probably fix this
myCharacter.CurrentHP++;
}
public void HPDecrease_Click(object sender, RoutedEventArgs e)
{
myCharacter.CurrentHP--;
}
}
Character Model(去掉了很多不相关的属性)
public class Character
{
public int TotalHP { get; set; } //TODO not public
public int CurrentHP {get;set;} //TODO check vs total HP and 0
//constructor for creating a new character with provided stats
public Character (int strength, int dexterity, int constitution, int intelligence, int wisdom, int charisma)
{
this.TotalHP = 50;
this.CurrentHP = 45;
}
}
- 我的所有属性最初似乎都能正确找到
- 当我单击按钮更改 CurrentHP 时,我没有在 XAML 上看到这反映出来
- 我知道 prism 和 template 10 存在。我不想使用它们,因为我正在编写此代码以更好地理解这些东西以准备认证。将来我可能会利用它们,但我想弄清楚在这种情况下我做错了什么。
到目前为止,我的理解是我应该只将 INotfyPropertyChanged 放在 ViewModel 上,它可以处理自定义对象(在本例中为 Character)内的任何 属性 已更改的警报。
我错了吗? 我的角色 class 是否需要 INotifyPropertyChanged 才能正确提醒 XAML 这些更改?
感谢您在这里提供任何意见。
在您的视图模型中,您已经实现了 INotifyPropertyChanged
,因此如果您将 Character
设置为一个新对象,事件将被执行并且 WPF 将更新。
问题是当 Character
的 属性 改变时,没有发送通知事件,WPF 不知道刷新它的值。
您可以在 Character
中实现接口,在视图模型上触发 INotifyPropertyChanged
,或者将 Character
的 public 属性更改为依赖属性.
有两件事会阻止您的 UI 更新:
- 您的
Character
未实现 INotifyPropertyChanged,因此 UI 不会收到有关更改的通知。实现它并在适当的设置器中调用 OnPropertyChanged,否则你将不得不在myCharacter
上调用 OnPropertyChanged,这应该会刷新整个 字符,但第一种方法更好, - 第二个重要的事情是它也不会工作,除非你让你绑定 OneWay -
x:Bind
默认为 OneTime,所以你应该更正:
<TextBlock Name="HPTB" Text="{x:Bind CharacterViewModel.myCharacter.CurrentHP, Mode="OneWay"}"...