WPF4/C# - System.StackOverflowException 崩溃应用程序

发布于 2024-11-15 00:24:25 字数 3885 浏览 3 评论 0原文

下面您可以看到我的 .xaml.cs 代码。该应用程序打开良好。有 4 个文本框可供用户更改。当您编辑文本框中的默认值之一,然后单击“关闭”以不选择它时,应用程序会崩溃并出现 System.StackOverflowException 错误,提示我在 get{} 或 Calc() 函数上存在无限循环或递归,取决于编辑哪个文本框。我希望应用程序在每次未编辑文本框时根据 Calc() 函数计算数字。我还想为文本框定义一些起始值,但还没有弄清楚如何做到这一点。

有什么想法可以修复循环错误和初始值定义吗?

.xaml 代码中的文本框遵循以下模式: Text="{Binding DistanceBox}"

完整的后台代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace ConverterApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new Variables();
        }
    }

    public class Variables : INotifyPropertyChanged
    {
        // Declare the PropertyChanged event.
        public event PropertyChangedEventHandler PropertyChanged;

        private double m_distanceBox;
        public double DistanceBox
        {
            get { return m_distanceBox; }
            set
            {
                //If value hasn't changed, don't do anything
                //if (m_distanceBox == value)
                //    return;
                m_distanceBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property
                // is updated.
                //if(PropertyChanged!= null)
                    NotifyPropertyChanged("DistanceBox");
            }
        }

        private double m_widthBox;
        public double WidthBox
        {
            get { return m_widthBox; }
            set
            {
                m_widthBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property
                // is updated.
                NotifyPropertyChanged("WidthBox");
            } 
        }

        private double m_lengthBox;
        public double LengthBox
        {
            get { return m_lengthBox; }
            set
            {
                m_lengthBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property
                // is updated.
                NotifyPropertyChanged("LengthBox");
            }
        }

        private double m_lensBox;
        public double LensNeeded
        {
            get { return m_lensBox; }
            set
            {
                m_lensBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property
                // is updated.
                NotifyPropertyChanged("LensNeeded");
            }
        }

        public void Calc()
        {
            double WidthBased = 2.95 * (DistanceBox / WidthBox);
            double LengthBased = 3.98 * (DistanceBox / LengthBox);

            if (WidthBased < LengthBased)
            {
                LensNeeded = Math.Round(WidthBased,2);
            }else{
                LensNeeded = Math.Round(LengthBased,2);
            }
        }

        // NotifyPropertyChanged will raise the PropertyChanged event,
        // passing the source property that is being updated.
        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this,
                    new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

Below you can see my .xaml.cs code. The app opens fine. There are 4 textboxes which the user can change. When you edit one of the default values in the textboxes and then click off to not select it, the app crashes with the System.StackOverflowException error, saying I have an infinite loop or recursion on either the get{} or Calc() function, depending on which textbox is edited. I want the app to calculate the numbers according to the Calc() function every time a textbox is not being edited. I also would like to define some starting values for the textboxes, but haven't figured out how to do that yet.

Any ideas how I can fix the loop error and initial value defines?

The textboxes in the .xaml code follow this pattern: Text="{Binding DistanceBox}"

The full behind code is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace ConverterApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new Variables();
        }
    }

    public class Variables : INotifyPropertyChanged
    {
        // Declare the PropertyChanged event.
        public event PropertyChangedEventHandler PropertyChanged;

        private double m_distanceBox;
        public double DistanceBox
        {
            get { return m_distanceBox; }
            set
            {
                //If value hasn't changed, don't do anything
                //if (m_distanceBox == value)
                //    return;
                m_distanceBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property
                // is updated.
                //if(PropertyChanged!= null)
                    NotifyPropertyChanged("DistanceBox");
            }
        }

        private double m_widthBox;
        public double WidthBox
        {
            get { return m_widthBox; }
            set
            {
                m_widthBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property
                // is updated.
                NotifyPropertyChanged("WidthBox");
            } 
        }

        private double m_lengthBox;
        public double LengthBox
        {
            get { return m_lengthBox; }
            set
            {
                m_lengthBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property
                // is updated.
                NotifyPropertyChanged("LengthBox");
            }
        }

        private double m_lensBox;
        public double LensNeeded
        {
            get { return m_lensBox; }
            set
            {
                m_lensBox = value;
                // modify calc to read the text values
                Calc();
                // Call NotifyPropertyChanged when the source property
                // is updated.
                NotifyPropertyChanged("LensNeeded");
            }
        }

        public void Calc()
        {
            double WidthBased = 2.95 * (DistanceBox / WidthBox);
            double LengthBased = 3.98 * (DistanceBox / LengthBox);

            if (WidthBased < LengthBased)
            {
                LensNeeded = Math.Round(WidthBased,2);
            }else{
                LensNeeded = Math.Round(LengthBased,2);
            }
        }

        // NotifyPropertyChanged will raise the PropertyChanged event,
        // passing the source property that is being updated.
        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this,
                    new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

红ご颜醉 2024-11-22 00:24:25

LensNeeded 的 setter 中调用 Calc,calc 依次设置 ​​LensNeededLensNeeded 的 setter 调用 Calc等,这种循环导致了StackOverflow。

不要像这样计算 setter 中的属性,使相应的属性成为“虚拟”(动态计算值而不是从支持字段获取值),例如,

public double WidthBased
{
    get { return 2.95 * (DistanceBox / WidthBox); }
}

要更新此类属性的绑定,您可以在以下位置引发属性更改事件:所有相关属性的设置器,这里是 DistanceBoxWidthBox 的设置器。

private double m_distanceBox;
public double DistanceBox
{
    get { return m_distanceBox; }
    set
    {
        if (m_distanceBox != value)
        {
            m_distanceBox = value;
            NotifyPropertyChanged("DistanceBox");
            NotifyPropertyChanged("WidthBased");
        }
    }
}

初始值可以在变量类的构造函数中设置,也可以直接在字段声明中设置,例如

private double m_distanceBox = 10;
public double DistanceBox //...

In your setter of LensNeeded you call Calc, calc in turn sets LensNeeded, the setter of LensNeeded calls Calc, etc. this circularity leads to the StackOverflow.

Do not calculate properties in setters like that, make the respective properties "virtual" (calculate the value on the fly rather than getting the value from a backing field), e.g.

public double WidthBased
{
    get { return 2.95 * (DistanceBox / WidthBox); }
}

To make the bindings to such properties update you can raise property changed events in all related properties' setters, here that would be the setters of DistanceBox and WidthBox.

private double m_distanceBox;
public double DistanceBox
{
    get { return m_distanceBox; }
    set
    {
        if (m_distanceBox != value)
        {
            m_distanceBox = value;
            NotifyPropertyChanged("DistanceBox");
            NotifyPropertyChanged("WidthBased");
        }
    }
}

Initial values could be set in the contructor of your variables class or directly in the field declarations, e.g.

private double m_distanceBox = 10;
public double DistanceBox //...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文