Search code examples
c#wpfdata-binding

How to manage textbox changes when building complicated financial calculation in WPF


I am building a wpf application for some complicated financial calculation using textbox. The spreadsheet example

All grey cells are based on the formula.

I know I can use textbox_textChanges to track single textbox change, I tried to create some general textchange Method like the below:

    private void Txt_onTextChanged(object sender, TextChangedEventArgs e)
    {
        textbox.Text = int.Parse(!string.IsNullOrEmpty(textbox1.Text) ? textbox1.Text : "0") +
                       int.Parse(!string.IsNullOrEmpty(textbox1.Text) ? textbox1.Text : "0")
    }

It doesn't work well since I have so many different textboxes and calculations. (When the interest Basis changed, 3 more cells are changed) Is there an efficient way to track those changes and automatically reflect on the other textbox? I don't want to create text_TextChanges for eahch single Textbox, and the calculation method is not the same.


Solution

  • Finally I found a way to realize those functions. Using Converter.

       public class AddListRecordsConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                decimal val = 0;
                decimal result = 0;
    
                foreach (var txt in values)
                {
                    if (string.IsNullOrEmpty(txt.ToString())) continue;
                    if (decimal.TryParse(txt.ToString(), out val))
                        result += val;
                    else
                        return "$0.00";
                }
    
                return result.ToString();
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                return null;
            }
        }
    
    public class InterestCalculationRecordsConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                decimal val = 0;
                decimal result = 0;
                List<decimal> convertedLists = new List<decimal>();
                foreach (var txt in values)
                {
                    if (string.IsNullOrEmpty(txt.ToString())) return null;
                    if (decimal.TryParse(txt.ToString(), out val))
                        //result += val;
                        convertedLists.Add(val);
                    else
                        return "$0.00";
                }
    
                if (convertedLists[0] == 0) return 0;
                result = 1 / convertedLists[0] * convertedLists[1] * convertedLists[2] * convertedLists[3];
    
                return result.ToString();
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                return null;
            }
        }
    

    Xaml is like below.

     <Page.Resources>
            <local:AddListRecordsConverter x:Key="AddListRecordsConverter"></local:AddListRecordsConverter>
            <local:InterestCalculationRecordsConverter x:Key="InterestCalculationRecordsConverter"></local:InterestCalculationRecordsConverter>
     </Page.Resources>
    

    Textbox Xaml is like below (just post the int calculate):

    <TextBox Grid.Row="7" Grid.Column="2" Name="TxtPostJudgmentInterest" IsEnabled="False">
        <TextBox.Text>
            <MultiBinding Converter="{StaticResource InterestCalculationRecordsConverter}">
                <Binding ElementName="TxtYearDays" Path="Text" Mode="OneWay"></Binding>
                <Binding ElementName="TxtDays" Path="Text" Mode="OneWay"></Binding>
                <Binding ElementName="TxtPrincipal" Path="Text" Mode="OneWay"></Binding>
                <Binding ElementName="TxtInt" Path="Text" Mode="OneWay"></Binding>
            </MultiBinding>
        </TextBox.Text>
    </TextBox>