从 ComboBox 中选择的值未传递给 WPF MVVM 应用程序中的方法

问题描述 投票:0回答:0

我正在使用 WPF 和 MVVM 模式构建一个复利计算器。我的视图中有一个组合框,允许用户选择复合间隔(例如“每日”、“每周”、“每月”等)。此 ComboBox 的 ItemsSource 绑定到我的视图模型中的 ObservableCollection 属性,并且 SelectedItem 绑定到 SelectedCompoundInterval 属性。

当用户从 ComboBox 中进行选择时,我希望 SelectedCompoundInterval 属性的值会相应更新。但是,当我在视图模型中调用使用此属性作为计算输入的计算方法时,SelectedCompoundInterval 属性的值始终为空。

MyViewModel 类

namespace CompoundInterestCalculator
{
    internal class MyViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private Calculations _calculations = new Calculations();

            private bool _showResults;
            private decimal _initialAmount;
            public decimal InitialAmount
            {
                get { return _initialAmount; }
                set
                {
                    _initialAmount = value;
                Debug.WriteLine(_initialAmount.ToString());
                    OnPropertyChanged(nameof(InitialAmount));
                }
            }

            private decimal _interestRate;
            public decimal InterestRate
            {
                get { return _interestRate; }
                set
                {
                    _interestRate = value;
                    OnPropertyChanged(nameof(InterestRate));
                }
            }

            private int _years;
            public int Years
            {
                get { return _years; }
                set
                {
                    _years = value;
                    OnPropertyChanged(nameof(Years));
                }
            }

            private int _months;
            public int Months
            {
                get { return _months; }
                set
                {
                    _months = value;
                    OnPropertyChanged(nameof(Months));
                }
            }

            public ObservableCollection<string> CompoundIntervals { get; } = new ObservableCollection<string>
    {
        "Daily","Weekly", "Monthly", "Quarterly", "Yearly"

    };

            private string _selectedCompoundInterval;
            public string SelectedCompoundInterval
        {
            get { return _selectedCompoundInterval; }
            set
            {
                if (_selectedCompoundInterval != value)
                {
                    _selectedCompoundInterval = value;
                    OnPropertyChanged(nameof(SelectedCompoundInterval));

                    Debug.WriteLine("SelectedCompoundInterval changed: " + value);
                }

            }
        }

        public ObservableCollection<string> InterestRateTypes { get; } = new ObservableCollection<string>
{
    "Percent", "Decimal"
};

        private string _selectedInterestRateType;
            public string SelectedInterestRateType
            {
                get { return _selectedInterestRateType; }
                set
                {
                    _selectedInterestRateType = value;
                    OnPropertyChanged(nameof(SelectedInterestRateType));
                }
            }


            public DataTemplate CurrentTemplate
            {
                get
                {
                    if (_showResults)
                        return (DataTemplate)Application.Current.FindResource("ResultsTemplate");
                    else
                        return (DataTemplate)Application.Current.FindResource("InputTemplate");
                }
            }

            public void Calculate()
            {
            Debug.WriteLine("CompoundIntervals: " + string.Join(", ", CompoundIntervals));
            Debug.WriteLine("SelectedCompoundInterval: " + SelectedCompoundInterval);
            // Perform calculations here
            decimal initialAmount = InitialAmount;
            decimal interestRate = InterestRate;
            int years = Years;
            int months = Months;
            string compoundInterval = SelectedCompoundInterval;
            Debug.WriteLine("compoundInterval: " + compoundInterval);
            string interestRateType = SelectedInterestRateType;

            decimal totalAmount = _calculations.CalculationsAmounts(initialAmount, interestRate, years, months, compoundInterval, interestRateType);


            
                // Show results
                _showResults = true;
                OnPropertyChanged(nameof(CurrentTemplate));
            }


            
        }

    }

计算课

namespace CompoundInterestCalculator
{
    
    internal class Calculations
    {

       
        public decimal CalculationsAmounts(decimal initialAmount, decimal interestRate, int years, int months, string compoundInterval, string interestRateType)
        {

            Debug.WriteLine("compoundInterval: " + compoundInterval);

            int compoundFrequency;
            switch (compoundInterval)
            {
                case "Daily":
                    compoundFrequency = 365;
                    break;
                case "Weekly":
                    compoundFrequency = 52;
                    break;
                case "Monthly":
                    compoundFrequency = 12;
                    break;
                case "Quarterly":
                    compoundFrequency = 4;
                    break;
                case "Yearly":
                    compoundFrequency = 1;
                    break;
                default:
                    throw new ArgumentException("Invalid compound interval");

            }

            if (interestRateType == "Percent")
            {
                interestRate /= 100;
            }

            decimal totalAmount = initialAmount * (decimal)Math.Pow((double)(1 + interestRate / compoundFrequency), years * compoundFrequency + months * (compoundFrequency / 12));

            return totalAmount;
        }
    }
}

MainWindow.xaml.cs代码

namespace CompoundInterestCalculator
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private MyViewModel _myViewModel;
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MyViewModel();
            _myViewModel = new MyViewModel();
            
        }

        private void CalculateButton_Click(object sender, RoutedEventArgs e)
        {
            MyContentControl.ContentTemplate = (DataTemplate)FindResource("ResultsTemplate");
            _myViewModel.Calculate();
            
        }
        private void BackButton_Click(object sender, RoutedEventArgs e)
        {
            MyContentControl.ContentTemplate = (DataTemplate)FindResource("InputTemplate");
        }

        private void NumericOnly(object sender, TextCompositionEventArgs e)
        {
            e.Handled = IsTextNumeric(e.Text);
        }

        private static bool IsTextNumeric(string str)
        {
            System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("[^0-9]");
            return reg.IsMatch(str);
        }
        private void NumericDecimalOnly(object sender, TextCompositionEventArgs e)
        {
            TextBox textBox = sender as TextBox;
            if (textBox != null)
            {
                string newText = textBox.Text.Insert(textBox.CaretIndex, e.Text);
                decimal value;
                if (!decimal.TryParse(newText, out value) || value < 0.01m || value > 99.9999999m)
                {
                    e.Handled = true;
                }
            }
        }
        private void NumericMonthlyOnly(object sender, TextCompositionEventArgs e)
        {
            TextBox textBox = sender as TextBox;
            if (textBox != null)
            {
                string newText = textBox.Text.Insert(textBox.CaretIndex, e.Text);
                int value;
                if (!int.TryParse(newText, out value) || value < 1 || value > 12)
                {
                    e.Handled = true;
                }
            }
        }


    }
}

MainWindow.xaml ComboBox 代码

 <ComboBox Grid.Column="1" ItemsSource="{Binding CompoundIntervals}" SelectedItem="{Binding SelectedCompoundInterval, Mode=TwoWay}" Margin="10,5,0,0" Width="100" Height="20">
                    </ComboBox>

我尝试在多个地方调试程序,我注意到 ObservableCollection 正确填充了组合框,并且在调试 SelectedCompoundInterval 属性时,每次我在程序内更改它时,它都会通知我,在我的计算中使用的compoundInterval字符串应该具有要存储的东西。

我认为这意味着问题出在该点和我计算时之间的某个位置,因为调试计算代码中的compoundInterval字符串总是显示一个Null值,然后switch语句抛出一个argumentException,因为它不适合任何情况空值。

c# wpf xaml data-binding switch-statement
© www.soinside.com 2019 - 2024. All rights reserved.