I need a TextBox which is binded to ClassA showing the sum of a variable from two Objects from ClassB. It does only change its Value if i try to edit the TextBox manually. My problem is i dont know how i can implement a method in ClassA which listenes if the variables in ClassB are changed. I tried to make ClassB a SubClass from ClassA but then i get an StackOverflowException so that doesnt work.
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));
}
}
}
CodePudding user response:
You can use from Action
.
ClassA:
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));
}
ClassB:
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();
}
}
}
CodePudding user response:
Make ClassA
listen to each of its ClassB
objects using INotifyPropertyChanged
and the WPF PropertyChangedEventManager
. When the Var
property on either one changes, ClassA
can raise a PropertyChanged
event for its Sum
property. For example you might write a constructor for class A to do it
public ClassA()
{
PropertyChangedEventManager.AddHandler(
MyClassB1,
(_,_) => OnPropertyChanged(nameof(Sum)),
nameof(ClassB.Var));
PropertyChangedEventManager.AddHandler(
MyClassB2,
(_,_) => OnPropertyChanged(nameof(Sum)),
nameof(ClassB.Var));
}
But there is a problem: You have a public setter for ClassA.Sum
. How can that possibly work if Sum
is supposed to be the addition of each two ClassB.Var
values? How do you go in the other direction?
Each time someone sets ClassA.Sum
You would have to divide the new Sum between the two ClassB
's somehow or the next time somebody called the getter, the value would change back.
I don't know how that's going to work.