自定义对象中属性的显式 setter
Explicit setter for properties within custom object
我想为我的自定义对象提供明确的 setter:
字符class
public class CharacterModel
{
public int HP { get; set; }
public int MP { get; set; }
}
Main.razor
<input type="text" @bind-value="Character.HP" />
<input type="text" @bind-value="Character.MP" />
@code {
private CharacterModel character;
public CharacterModel Character
{
get => character;
set
{
character = value;
// Do something else
}
}
}
我的问题是目前代码中的 setter 没有 运行,因为它正在调用 HP 和 MP setter。当我更改 HP 和 MP 时,有没有办法在代码中调用 setter?
简而言之:不。由于您绑定到 Character.HP
和 Character.MP
,因此您没有更改 属性 Character
,而是模型绑定仅更改该对象的值直接。如果你做这样的事情也是如此:
// setter is called for this:
this.Character = new CharacterModel();
// setter is not called for this:
this.Character.HP = 100;
this.Character.MP = 50;
这样做的原因是因为它在功能上等同于以下内容:
// getter is used to retrieve object:
var character = this.Character;
// only operates on a local reference:
character.HP = 100;
character.MP = 50;
如果您需要找出角色模型的 属性 何时更改,那么您可以按照通常在 MVVM 设置中使用的方法进行操作。您可以让 CharacterModel
实现 INotifyPropertyChanged
interface,让它通知相关方 属性 更改:
public class CharacterModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int _hp;
public int HP
{
get => _hp;
set
{
_hp = value;
RaisePropertyChanged();
}
}
private int _mp;
public int MP
{
get => _mp;
set
{
_mp = value;
RaisePropertyChanged();
}
}
private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
是的,不幸的是,这给您的模型类型增加了很多膨胀,但从好的方面来说,它现在是完全反应式的。因此您可以订阅对其属性的更改:
private CharacterModel character;
public CharacterModel Character
{
get => character;
set
{
// nothing to do if the value hasn’t changed
if (character == value)
return;
// remove existing event handler
if (character != null)
character.PropertyChanged -= HandlePropertyChanged;
// store new value
character = value;
// add event handler
if (character != null)
character.PropertyChanged += HandlePropertyChanged;
}
}
private void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(CharacterModel.HP))
{
// HP has changed, do something
InvokeAsync(async () =>
{
highlightHealthPotion = Character.HP < 20;
StateHasChanged()
}
}
}
我想为我的自定义对象提供明确的 setter:
字符class
public class CharacterModel
{
public int HP { get; set; }
public int MP { get; set; }
}
Main.razor
<input type="text" @bind-value="Character.HP" />
<input type="text" @bind-value="Character.MP" />
@code {
private CharacterModel character;
public CharacterModel Character
{
get => character;
set
{
character = value;
// Do something else
}
}
}
我的问题是目前代码中的 setter 没有 运行,因为它正在调用 HP 和 MP setter。当我更改 HP 和 MP 时,有没有办法在代码中调用 setter?
简而言之:不。由于您绑定到 Character.HP
和 Character.MP
,因此您没有更改 属性 Character
,而是模型绑定仅更改该对象的值直接。如果你做这样的事情也是如此:
// setter is called for this:
this.Character = new CharacterModel();
// setter is not called for this:
this.Character.HP = 100;
this.Character.MP = 50;
这样做的原因是因为它在功能上等同于以下内容:
// getter is used to retrieve object:
var character = this.Character;
// only operates on a local reference:
character.HP = 100;
character.MP = 50;
如果您需要找出角色模型的 属性 何时更改,那么您可以按照通常在 MVVM 设置中使用的方法进行操作。您可以让 CharacterModel
实现 INotifyPropertyChanged
interface,让它通知相关方 属性 更改:
public class CharacterModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int _hp;
public int HP
{
get => _hp;
set
{
_hp = value;
RaisePropertyChanged();
}
}
private int _mp;
public int MP
{
get => _mp;
set
{
_mp = value;
RaisePropertyChanged();
}
}
private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
是的,不幸的是,这给您的模型类型增加了很多膨胀,但从好的方面来说,它现在是完全反应式的。因此您可以订阅对其属性的更改:
private CharacterModel character;
public CharacterModel Character
{
get => character;
set
{
// nothing to do if the value hasn’t changed
if (character == value)
return;
// remove existing event handler
if (character != null)
character.PropertyChanged -= HandlePropertyChanged;
// store new value
character = value;
// add event handler
if (character != null)
character.PropertyChanged += HandlePropertyChanged;
}
}
private void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(CharacterModel.HP))
{
// HP has changed, do something
InvokeAsync(async () =>
{
highlightHealthPotion = Character.HP < 20;
StateHasChanged()
}
}
}