C# WPF中依赖值FeesAmount不更新问题求助
问题:WPF中修改FeesPercentage后FeesAmount未更新
场景与代码
XAML布局
<StackPanel> <Label>Fee Percentage:</Label> <TextBox Text="{Binding ContractExtension.FeesPercentage, UpdateSourceTrigger=PropertyChanged}"></TextBox> </StackPanel> <StackPanel> <Label>Amount in $</Label> <TextBox Text="{Binding FeesAmount, Mode=OneWay}" IsReadOnly="True"></TextBox> </StackPanel>
MainViewModel代码
public class MainViewModel : BaseViewModel { private ContractExtension contractExtension; public ContractExtension ContractExtension { get { return contractExtension; } set { contractExtension = value; OnPropertyChanged(nameof(ContractExtension)); OnPropertyChanged(nameof(FeesAmount)); } } public decimal FeesAmount { get { decimal feesAmount = Toolbox.GetContractGivenValue(contract, false) * ContractExtension.FeesPercentage / 100; return feesAmount; } } }
BaseViewModel代码
public abstract class BaseViewModel : INotifyPropertyChanged { #region Attributes private Window parentWindow; #endregion Attributes #region Properties public Window ParentWindow { get { return parentWindow; } set { parentWindow = value; SetParentWindow(value); } } public abstract void SetParentWindow(Window parentWindow); public SearchBoxViewModel SearchBoxViewModel { get; } #endregion Properties public event PropertyChangedEventHandler? PropertyChanged; public abstract void ResetData(); protected static ExceptionManager exceptionManager; public BaseViewModel() { exceptionManager = new ExceptionManager(); SearchBoxViewModel = new SearchBoxViewModel(); } protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public void RefreshProperty(string propertyName) { OnPropertyChanged(propertyName); } }
问题现象
修改第一个文本框的FeesPercentage值时,第二个文本框的FeesAmount未同步更新。调试发现:初始化时会进入ContractExtension的setter,但编辑FeesPercentage时不会触发该setter,因此无法执行OnPropertyChanged(nameof(FeesAmount))。
已排查内容
- 确认ContractExtension实现了INotifyPropertyChanged
- 验证DataContext设置正确
- 确认FeesPercentage变化时会触发自身的setter
解决方案
当前代码仅在替换整个ContractExtension对象时才会触发FeesAmount的PropertyChanged,但编辑FeesPercentage是修改ContractExtension内部属性,对象引用未变,所以MainViewModel的ContractExtension setter不会被调用。需要监听ContractExtension的PropertyChanged事件,在FeesPercentage变化时主动刷新FeesAmount。
修改MainViewModel
private ContractExtension contractExtension; public ContractExtension ContractExtension { get { return contractExtension; } set { // 移除旧对象的事件监听 if (contractExtension != null) { contractExtension.PropertyChanged -= ContractExtension_PropertyChanged; } contractExtension = value; // 添加新对象的事件监听 if (contractExtension != null) { contractExtension.PropertyChanged += ContractExtension_PropertyChanged; } OnPropertyChanged(nameof(ContractExtension)); OnPropertyChanged(nameof(FeesAmount)); } } private void ContractExtension_PropertyChanged(object? sender, PropertyChangedEventArgs e) { // 当FeesPercentage属性变化时,触发FeesAmount的更新 if (e.PropertyName == nameof(ContractExtension.FeesPercentage)) { OnPropertyChanged(nameof(FeesAmount)); } }
确保ContractExtension的FeesPercentage正确触发事件
确认ContractExtension中FeesPercentage的setter正确触发PropertyChanged:
// ContractExtension中的示例实现 private decimal feesPercentage; public decimal FeesPercentage { get => feesPercentage; set { if (feesPercentage != value) { feesPercentage = value; OnPropertyChanged(nameof(FeesPercentage)); } } }
补充说明
若其他模块用相同方式正常工作,大概率是那些模块中存在替换整个对象的操作,或已隐式处理了子对象的PropertyChanged监听。
内容的提问来源于stack exchange,提问作者Elzardi
相关产品推荐
相关产品推荐

