我想,一旦我更改了txtA的值,txtB和txtC就会自动更改,因为我已经为ValueA实现了INotifyPropertyChanged。
txtB 始终为 100,txtC 始终为 -50。
我不知道是什么原因。
我的Xaml..
<Window x:Class="WpfApplicationReviewDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBox Name="txtA" Text="{Binding ValueA}" />
<TextBox Name="txtB" Text="{Binding ValueB}" />
<TextBox Name="txtC" Text="{Binding ValueC}" />
</StackPanel>
</Window>
我的代码隐藏...
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new Model();
}
}
public class Model : INotifyPropertyChanged
{
private decimal valueA;
public decimal ValueA { get {
return valueA;
}
set
{
valueA = value;
PropertyChanged(this, new PropertyChangedEventArgs("ValueA"));
}
}
private decimal valueB;
public decimal ValueB
{
get
{
valueB = ValueA + 100;
return valueB;
}
set
{
valueB = value;
PropertyChanged(this, new PropertyChangedEventArgs("ValueB"));
}
}
private decimal valueC;
public decimal ValueC
{
get
{
valueC = ValueA - 50;
return valueC;
}
set
{
valueC = value;
PropertyChanged(this, new PropertyChangedEventArgs("ValueC"));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
将代码添加到 ValueA 属性的设置方法后,它可以工作。
public decimal ValueA { get {
return valueA;
}
set
{
valueA = value;
PropertyChanged(this, new PropertyChangedEventArgs("ValueA"));
PropertyChanged(this, new PropertyChangedEventArgs("ValueB"));
PropertyChanged(this, new PropertyChangedEventArgs("ValueC"));
}
}
但我认为它应该针对 txtB 和 txtC 自动刷新/更新。请指教。
我会这样处理
public class Model : INotifyPropertyChanged
{
private decimal valueA;
public decimal ValueA
{
get { return valueA; }
set
{
if( valueA != value )
{
valueA = value;
PropertyChanged(this, new PropertyChangedEventArgs("ValueA"));
PropertyChanged(this, new PropertyChangedEventArgs("ValueB"));
PropertyChanged(this, new PropertyChangedEventArgs("ValueC"));
}
}
}
public decimal ValueB
{
get { return ValueA + 100; }
}
public decimal ValueC
{
get { return ValueA - 50; }
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
或作为
public class Model2 : INotifyPropertyChanged
{
private decimal valueA;
private decimal valueB;
private decimal valueC;
public decimal ValueA
{
get { return valueA; }
set
{
if( valueA != value )
{
valueA = value;
PropertyChanged(this, new PropertyChangedEventArgs("ValueA"));
ValueB = value + 100;
ValueC = value - 50;
}
}
}
public decimal ValueB
{
get { return valueB; }
private set
{
valueB = value;
PropertyChanged(this, new PropertyChangedEventArgs("ValueB"));
}
}
public decimal ValueC
{
get { return valueC; }
private set
{
valueC = value;
PropertyChanged(this, new PropertyChangedEventArgs("ValueC"));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
开箱即用,它不知道属性B和C依赖于A。你需要像你所做的那样告诉它。
PropertyChanged
允许任何数据绑定到属性已更改的对象。更改文本框的值时,请遵循代码的逻辑。对值 A 调用 set 方法,将值 A 设置为值。
set
{
valueA = value;
PropertyChanged(this, new PropertyChangedEventArgs("ValueA"));
}
但是,当调用 PropertyChanged 时,它所做的只是让 TextBox 知道值已更改(它已经知道,因为它调用了 set 方法)。另一个第二个 set 方法工作的原因是,它通知其他 TextBox 其属性也已更改,因此它们需要反映更改。
set
{
valueA = value;
PropertyChanged(this, new PropertyChangedEventArgs("ValueA"));
PropertyChanged(this, new PropertyChangedEventArgs("ValueB"));
PropertyChanged(this, new PropertyChangedEventArgs("ValueC"));
}
这允许所有三个文本框更新显示以显示新值。
您正在谈论的方案通常称为"计算"或"计算"属性。但是,通常建议将它们设置为只读。只读计算简化了代码,意味着无需支持字段来存储值。
正如您已经计算的那样,INotifyPropertyChanged 不会"自动"检测这些依赖项。您需要根据依赖项显式触发事件。
这实际上是使用 ILWeaving 的完美案例。原因是在编译时,ILWeaving 可以检测这些依赖项并正确触发多个事件。
例如,如果您使用 NotifyPropertyWeaver http://code.google.com/p/notifypropertyweaver/则可以像这样编写代码。
public class Model : INotifyPropertyChanged
{
public decimal ValueA { get; set; }
public decimal ValueB
{
get { return ValueA + 100;}
}
public decimal ValueC
{
get { return ValueA - 50; }
}
public event PropertyChangedEventHandler PropertyChanged;
}
并编译此内容
public class Model : INotifyPropertyChanged
{
public virtual void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
decimal valueA;
public decimal ValueA
{
get { return valueA; }
set
{
if (!decimal.Equals(valueA, value))
{
valueA = value;
OnPropertyChanged("ValueB");
OnPropertyChanged("ValueC");
OnPropertyChanged("ValueA");
}
}
}
public decimal ValueB
{
get { return ValueA + 100;}
}
public decimal ValueC
{
get { return ValueA - 50; }
}
public event PropertyChangedEventHandler PropertyChanged;
}
请注意,方法OnPropertyChanged与三个调用一起注入到"A"的setter中。
请注意,"B"和"C"文本框也应该是只读的
<TextBox Name="txtA" Text="{Binding ValueA}" />
<TextBox Name="txtB" Text="{Binding ValueB}" IsReadOnly="True" />
<TextBox Name="txtC" Text="{Binding ValueC}" IsReadOnly="True" />