Как сообщать об изменениях расчетного привязанного свойства класса в WPF?

106
01 апреля 2021, 05:30

Подскажите, пожалуйста, где я не прав.
Я создал класс Bill, в котором есть ряд полей.
Есть форма, на которой расположены TextBlock'и в них попадают значения полей класса Bill через Binding
Вопрос в следующем - как мне просуммировать значения TextBlock и вывести сумму в поле Total?
Вот класс Bill

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BindWork.Models
{
    public class Bill : INotifyPropertyChanged
    {
        private int hotwater;
        private int coldwater;
        private int electric;
        private int hotwatertax;
        private int coldwatertax;
        private int electrictax;
        private int total;
        public int HotWaterTax
        {
            get { return hotwatertax; }
            set
            {
                hotwatertax = value;
            }
        }
        public int ColdWaterTax
        {
            get { return coldwatertax; }
            set
            {
                coldwatertax = value;
            }
        }
        public int ElectricTax
        {
            get { return electrictax; }
            set
            {
                electrictax = value;
            }
        }

        public int HotWater
        {
            get { return hotwater; }
            set
            {
                hotwater = value;
                total += hotwater;
                OnPropertyChanged("HotWater");
            }
        }
        public int ColdWater
        {
            get { return coldwater; }
            set
            {
                coldwater = value;
                OnPropertyChanged("ColdWater");
            }
        }
        public int Electric
        {
            get { return electric; }
            set
            {
                electric = value;
                OnPropertyChanged("Electric");
            }
        }
        public int Total
        {
            get
            {
                return total = coldwater + hotwater + electric ;
            }
            set
            {
                OnPropertyChanged("ColdWater");
                OnPropertyChanged("HotWater");
                OnPropertyChanged("Electric");
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(String info)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(info));
            }
        }
    }
}

А вот форма

<Window
        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:BindWork"
        xmlns:Models="clr-namespace:BindWork.Models" x:Class="BindWork.MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="FontSize" Value="36"/>
        </Style>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="FontSize" Value="36"/>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.DataContext>
            <Models:Bill/>
        </Grid.DataContext>

        <TextBox Text="{Binding Path=ColdWater, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Height="57" Margin="10,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="231" Cursor=""/>
        <TextBox Text="{Binding Path=HotWater, UpdateSourceTrigger=PropertyChanged}"  HorizontalAlignment="Left" Height="57" Margin="10,70,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="231" />
        <TextBox Text="{Binding Path=Electric, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Height="57" Margin="10,132,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="231" />
        <TextBlock x:Name="ColdWaterBill" Text="{Binding Path=ColdWater, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="435,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="57" Width="347" />
        <TextBox x:Name="ColdWaterTax" Text="{Binding Path=ColdWaterTax}" HorizontalAlignment="Left" Height="57" Margin="247,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="184" IsReadOnly="True" />
        <TextBox x:Name="HotWaterTax" DataContext="{Binding Source=Bill}" Text="{Binding Path=Electric}" HorizontalAlignment="Left" Height="57" Margin="246,70,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="184" IsReadOnly="True" />
        <TextBox x:Name="ElectricTax" HorizontalAlignment="Left" Height="57" Margin="246,132,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="184" IsReadOnly="True"/>
        <TextBlock x:Name="ElectricBill" Text="{Binding Path=Electric, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="435,132,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="57" Width="347" />
        <TextBlock x:Name="HotWaterBill"  Text="{Binding Path=HotWater, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="435,70,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="57" Width="347" />
        <TextBlock x:Name="TotalBill" Text="{Binding Path=Total, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" HorizontalAlignment="Left" Margin="435,194,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="57" Width="347" />
    </Grid>
</Window>

Где я ошибся?

Answer 1

Total же изменяться не будет? Тогда сеттер

set
{
    OnPropertyChanged("ColdWater");
    OnPropertyChanged("HotWater");
    OnPropertyChanged("Electric");
}

не вызывается и смысла не имеет. Тем более что оповещения для этих свойств и так генерируются при их изменении.

Нужно наоборот, там где происходят изменения генерировать событие изменения Total:

public int HotWater
{
    get { return hotwater; }
    set
    {
        hotwater = value;
        //total += hotwater; не нужно, Total и так пересчитывается
        OnPropertyChanged("HotWater");
        OnPropertyChanged("Total"); //Total тоже изменился
    }
}

Аналогично для двух других свойств. Предупреждение: код не тестировал, возможно есть другие проблемы, которых я не заметил.

Answer 2

Не хватало

OnPropertyChanged("Total");
READ ALSO
Как отправить картинку через телеграм бота не загружая ее на сервер?

Как отправить картинку через телеграм бота не загружая ее на сервер?

Пытаюсь написать бота,который накладывает текст,отправленный пользователем, на картинку(картинка одна и та же)Найти способ нормально загружать...

116
Сортировка перед GROUP_CONCAT и DISTINCT?

Сортировка перед GROUP_CONCAT и DISTINCT?

Не могу придумать как перед GROUP_CONCAT и DISTINCT отсортировать по ordering

130
Как можно заменить ID в таблице массово?

Как можно заменить ID в таблице массово?

в массиве есть данные вида:

130
Выборка данных, циклы

Выборка данных, циклы

Возникла следующая задача: вывести количество игроков онлайнЕсть такой код:

145