OnPropertyChanged() 仅通过手动编辑 TextBox 触发

OnPropertyChanged() only triggered by manually editing a TextBox

我需要一个绑定到 ClassA 的文本框,显示来自 ClassB 的两个对象的变量之和。 如果我尝试手动编辑文本框,它只会更改其值。我的问题是我不知道如何在 ClassA 中实现一个方法来监听 ClassB 中的变量是否发生变化。我试图使 ClassB 成为 ClassA 的子类,但随后我得到一个 WhosebugException,所以它不起作用。


MainWindow.xaml


<Window x:Class="INPCTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:INPCTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:ClassA/>
    </Window.DataContext>
    <Grid x:Name="BaseGrid" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="10" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="10"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBox x:Name="TextBoxClassA" Grid.Row="1" Grid.Column="1" Text="{Binding Sum, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox x:Name="TextBox1ClassB" Grid.Row="2" Grid.Column="1" Text="{Binding MyClassB1.Var, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox x:Name="TextBox2ClassB" Grid.Row="2" Grid.Column="2" Text="{Binding MyClassB2.Var, UpdateSourceTrigger=PropertyChanged}" />
    </Grid>
</Window>

ClassA.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace INPCTest
{
    public class ClassA : ObservableObject
    {

        private decimal _sum;



        public decimal Sum
        {
            get { _sum = MyClassB1.Var + MyClassB2.Var; return _sum; }
            set { _sum = value; OnPropertyChanged();}
        }


        public ClassB MyClassB1 { get; set; } = new ClassB(1);
        public ClassB MyClassB2 { get; set; } = new ClassB(2);

    }
}

ClassB.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace INPCTest
{
    public class ClassB : ObservableObject
    {
        private decimal _var;

        public ClassB(decimal var)
        {
            _var = var;
        }

        public decimal Var
        {
            get { return _var; }
            set { _var = value; OnPropertyChanged();}
        }


    }
}

ObservableObject.cs


using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace INPCTest
{
    public class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string propertyname = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
        }

    }
}

使用 INotifyPropertyChanged 和 WPF PropertyChangedEventManagerClassA 监听其每个 ClassB 对象。当其中任何一个的 Var 属性 发生变化时,ClassA 可以为其 Sum 属性 引发 PropertyChanged 事件。例如,您可以为 class A 编写一个构造函数来完成

public ClassA()
{
    PropertyChangedEventManager.AddHandler(
        MyClassB1,
        (_,_) => OnPropertyChanged(nameof(Sum)),
        nameof(ClassB.Var));

    PropertyChangedEventManager.AddHandler(
        MyClassB2,
        (_,_) => OnPropertyChanged(nameof(Sum)),
        nameof(ClassB.Var));
}

但是有一个问题:你有 public setter ClassA.Sum。如果 Sum 应该是每两个 ClassB.Var 值的相加,这怎么可能起作用?你怎么往另一个方向走?

每次有人设置 ClassA.Sum 时,您必须以某种方式在两个 ClassB 之间划分新的总和,或者下次有人调用 getter 时,该值会改变返回。

我不知道这是怎么回事。

您可以使用 Action.

A​​ 类:

public class ClassA : ObservableObject
{
    private decimal _sum;

    public ClassA()
    {
        MyClassB1 = new ClassB(1) {OnVarChanged = OnVarChange};
        MyClassB2 = new ClassB(2) {OnVarChanged = OnVarChange};
    }

    public decimal Sum
    {
        get { _sum = MyClassB1.Var + MyClassB2.Var; return _sum; }
        set { _sum = value; OnPropertyChanged(); }
    }


    public ClassB MyClassB1 { get; set; }
    public ClassB MyClassB2 { get; set; }

    private void OnVarChange() => OnPropertyChanged(nameof(Sum));
}

B 类:

public class ClassB : ObservableObject
{
    private decimal _var;

    public ClassB(decimal var)
    {
        _var = var;
    }

    public Action OnVarChanged { get; set; }

    public decimal Var
    {
        get { return _var; }
        set
        {
            _var = value;
            OnPropertyChanged();
            OnVarChanged?.Invoke();
        }
    }

}