0

我想,一旦我改变了 txtA 的值,txtB 和 txtC 就会自动改变,因为我已经为 ValueA 实现了 INotifyPropertyChanged。

但是它们没有在 UI 上更新。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 属性的 set 方法后,它就可以工作了。

    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 自动刷新/更新。请指教。

4

4 回答 4

3

我会处理这个

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
}
于 2012-06-22T07:32:39.050 回答
1

开箱即用它不知道属性 B 和 C 依赖于 A。您需要像您所做的那样告诉它。

于 2012-06-22T03:18:16.517 回答
1

PropertyChanged允许任何数据绑定到属性已更改的对象。当您更改文本框的值时,请遵循代码的逻辑。为 ValueA 调用 set 方法,并将 valueA 设置为 value。

set
{
    valueA = value;
    PropertyChanged(this, new PropertyChangedEventArgs("ValueA"));
}

但是,当调用 PropertyChanged 时,它所做的只是让 TextBox 知道值已更改(它已经知道,因为它调用了 set 方法)。另一个第二个 set 方法起作用的原因是它通知其他 TextBoxes 他们的属性也发生了变化,因此它们需要反映这些变化。

set
{
    valueA = value;
    PropertyChanged(this, new PropertyChangedEventArgs("ValueA"));
    PropertyChanged(this, new PropertyChangedEventArgs("ValueB"));
    PropertyChanged(this, new PropertyChangedEventArgs("ValueC"));
}

这让所有三个文本框都更新显示以显示新值。

于 2012-06-22T03:22:11.123 回答
0

您正在谈论的场景通常称为“计算”或“计算”属性。但是,通常建议将它们设为只读。只读计算简化了您的代码,这意味着您不需要支持字段来存储值。

正如您所了解的,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”的设置器中。

请注意,“B”和“C”文本框也应该是只读的

    <TextBox Name="txtA" Text="{Binding ValueA}" />
    <TextBox Name="txtB" Text="{Binding ValueB}" IsReadOnly="True" />
    <TextBox Name="txtC" Text="{Binding ValueC}" IsReadOnly="True" />
于 2012-06-24T02:11:10.570 回答