0

ValueAにINotifyPropertyChangedを実装しているため、txtAの値を変更すると、txtBとtxtCが自動的に変更されると思いました。

しかし、それらは 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

PropertyChangedプロパティが変更されたオブジェクトにデータバインドされているものはすべて許可します。テキストボックスの値を変更した場合は、コードのロジックに従ってください。ValueAに対してsetメソッドが呼び出され、valueAがvalueに設定されます。

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

ただし、PropertyChangedが呼び出されると、TextBoxに値が変更されたことを通知するだけです(setメソッドを呼び出したため、すでに認識されていることです)。他の2番目のsetメソッドが機能する理由は、他のTextBoxにプロパティも変更されたことを通知するため、変更を反映する必要があるためです。

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

これにより、3つのTextBoxすべてが表示を更新して新しい値を表示できます。

于 2012-06-22T03:22:11.123 に答える
1

そのままでは、プロパティ B と C が A に依存していることを認識していません。

于 2012-06-22T03:18:16.517 に答える
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" のセッターに 3 つの呼び出しと共に挿入されていることに注意してください。

「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 に答える