WPF4/C# - System.StackOverflowException 崩溃应用程序
下面您可以看到我的 .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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在
LensNeeded
的 setter 中调用Calc
,calc 依次设置 LensNeeded
,LensNeeded
的 setter 调用Calc
等,这种循环导致了StackOverflow。不要像这样计算 setter 中的属性,使相应的属性成为“虚拟”(动态计算值而不是从支持字段获取值),例如,
要更新此类属性的绑定,您可以在以下位置引发属性更改事件:所有相关属性的设置器,这里是
DistanceBox
和WidthBox
的设置器。初始值可以在变量类的构造函数中设置,也可以直接在字段声明中设置,例如
In your setter of
LensNeeded
you callCalc
, calc in turn setsLensNeeded
, the setter ofLensNeeded
callsCalc
, 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.
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
andWidthBox
.Initial values could be set in the contructor of your variables class or directly in the field declarations, e.g.