C# 无法计算表达式,因为当前线程处于堆栈溢出状态
正如我所学。。。我已经创建了一个简单的数据绑定项目,它可以很好地处理一段数据,例如firstName。但是,当我试图使用lastName编译器时,会抛出一个运行时错误,如 **无法计算表达式,因为当前线程处于堆栈溢出状态** 这是代码。如您所见,第二个字段(姓氏)被注释掉,因为它导致堆栈溢出。如有任何评论,我们将不胜感激C# 无法计算表达式,因为当前线程处于堆栈溢出状态,c#,wpf,xaml,C#,Wpf,Xaml,正如我所学。。。我已经创建了一个简单的数据绑定项目,它可以很好地处理一段数据,例如firstName。但是,当我试图使用lastName编译器时,会抛出一个运行时错误,如 **无法计算表达式,因为当前线程处于堆栈溢出状态** 这是代码。如您所见,第二个字段(姓氏)被注释掉,因为它导致堆栈溢出。如有任何评论,我们将不胜感激 public partial class MainWindow : Window { Person p; public MainWindow() {
public partial class MainWindow : Window
{
Person p;
public MainWindow()
{
InitializeComponent();
p = new Person();
p.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(p_PropertyChanged);
this.DataContext = p;
p.FirstName = p.OriginalFirstName;
p.LastName = p.OriginalLastName;
}
void p_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
stat1.Text = (p.OriginalFirstName == p.FirstName) ? "Original" : "Modified";
//stat2.Text = (p.OriginalLastName == p.LastName) ? "Original" : "Modifined";
}
}
编辑:
XAML:
每次更改属性时,您都会更改一个属性(文本值),该属性会触发另一个属性更改事件,该事件会更改文本属性,该属性会触发 你知道这是怎么回事吗 您需要在更改文本属性时禁用事件触发,或者不在属性已更改事件处理程序的上下文中更改它
由于我们没有您的
Person
类的详细信息,我们不知道它是否已经支持某种机制来禁用事件触发,或者在不触发事件的情况下更改值。如果不存在,您可能需要创建自己的。如何做到这一点将取决于该类的实现。我认为p_PropertyChanged方法应该是静态的,对方法的以下更改可以毫无问题地工作
static void p_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
MainWindow w = (MainWindow) sender;
w.stat1.Text = (w.p.OriginalFirstName == w.p.FirstName) ? "Original" : "Modified";
//stat2.Text = (p.OriginalLastName == p.LastName) ? "Original" : "Modifined";
}
但是如果您发布部分XAML代码会更好,因为您可能会以更干净的方式获得相同的结果
在使用WPF时,您几乎应该忘记一些winform编程代码实践。我认为您应该主要使用绑定和DependenciesProperty编写代码
编辑
public class Person : INotifyPropertyChanged
{
public string OriginalFirstName = "Jim";
public string OriginalLastName = "Smith";
private string _firstName;
#region FirstName
public string FirstName
{
get { return _firstName; }
set
{
if (value != null)
{
_firstName = value;
NotifyTheOtherGuy("CheckFirstName");
}
}
}
#endregion FirstName
private string _lastName;
#region LastName
public string LastName
{
get { return _lastName; }
set
{
if (value != null)
{
_lastName = value;
NotifyTheOtherGuy("CheckLastName");
}
}
}
#endregion LastName
public string CheckFirstName
{
get
{
return (FirstName==OriginalFirstName) ? "Original": "Modified";
}
}
public string CheckLastName
{
get
{
return (LastName==OriginalLastName) ? "Original": "Modified";
}
}
public Person()
{
}
public event PropertyChangedEventHandler PropertyChanged;
void NotifyTheOtherGuy(string msg)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(msg));
}
}
}
MainWindow类:所有精化任务都将从此类中删除,并且只有Person对象的DependecProperty定义
public partial class MainWindow : Window
{
public static readonly DependencyProperty MyPersonProperty;
static MainWindow()
{
MyPersonProperty = DependencyProperty.Register("MyPerson", typeof(Person), typeof(MainWindow));
}
Person MyPerson
{
set
{
SetValue(MyPersonProperty,value);
}
get
{
return GetValue(MyPersonProperty) as Person;
}
}
public MainWindow()
{
MyPerson = new Person();
InitializeComponent();
}
}
主窗口XAML:每个组件都以正确的方式绑定到Person DependencyProperty。文本框被绑定以更新Person属性值,文本块被绑定以获取检查属性的结果,该属性(如前所述)在Person类的其他属性更改后通知其更改
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="TryPrj.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prj="clr-namespace:TryPrj"
Title="TryPrj"
Height="300"
Width="300"
x:Name="myWindow">
<Grid>
<Grid.RowDefinitions>
<RowDefinition
Height="Auto" />
<RowDefinition
Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="100" />
<ColumnDefinition
Width="100" />
<ColumnDefinition
Width="100" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="0"
Grid.Row="0"
Content="First Name:" />
<Label
Grid.Row="1"
Content="Last Name:" />
<TextBox
Grid.Column="1"
Grid.Row="0"
Background="Yellow"
Margin="5"
FontWeight="Bold"
Text="{Binding Path=MyPerson.FirstName, Mode=OneWayToSource, ElementName=myWindow, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock
Grid.Column="2"
Text="{Binding Path=MyPerson.CheckFirstName, Mode=OneWay, ElementName=myWindow}"
/>
<TextBox
Grid.Column="1"
Grid.Row="1"
Background="Yellow"
Margin="5"
FontWeight="Bold"
Text="{Binding Path=MyPerson.LastName, Mode=OneWayToSource, ElementName=myWindow, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock
Grid.Column="2"
Grid.Row="1"
Text="{Binding Path=MyPerson.CheckLastName, Mode=OneWay, ElementName=myWindow}" />
</Grid>
</Window>
我认为XAML的这一块中的错误:
<TextBox Grid.Column="1" Grid.Row="0" Background="Yellow" Margin="5" FontWeight="Bold" Text="{Binding Path=FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock x:Name="stat1" Grid.Column="2" />
<TextBox x:Name="stat2" Grid.Column="1" Grid.Row="1" Background="Yellow" Margin="5" FontWeight="Bold" Text="{Binding Path=LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Grid.Column="2" Grid.Row="1" />
我想您希望最后一个TextBlock
前面有x:Name=“stat2”
,而不是TextBox
更改LastName
时,将调用PropertyChanged事件处理程序,从而更改stat2
的文本值。由于stat2
是TextBox
,其值通过two-way
绑定绑定到LastName
,这会导致绑定机制将您设置的值发送回视图模型。这会引发另一个PropertyChanged事件,从而更改stat2
的值,从而引发另一个PropertyChanged事件。。。。这种无休止的循环不会停止,这就是为什么会出现堆栈溢出错误
使用
FirstName
不会出现任何此类堆栈溢出,因为stat1
是一个TextBlock
,其Text
属性上没有绑定。您可以发布您的Person
类吗?编辑:另外,您的stat1
和stat2
文本字段是否绑定到此人?还要发布WPF控件的XAML。使用绑定到正确上下文的XAML修复了所有这些…多亏了所有。我刚刚添加了Person类。stat1和stat2是TextBlocksXaml文件。进行此更改应该会产生相同的结果。您仍在更改property changed事件中的属性,从而导致无限递归。只有当stat1.TextChanged由更改Person的方法处理时,才会发生这种情况。OP做过这样的事吗?你也知道另一种方式吗?我想也需要查看XAML代码。我已经发布了XAML和Person类。我尝试了静态编译,但编译器对此不满意。谢谢Luke。你说得对。在标签之间跳跃使我忘记了在哪里添加名称。这帮了大忙。
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="TryPrj.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prj="clr-namespace:TryPrj"
Title="TryPrj"
Height="300"
Width="300"
x:Name="myWindow">
<Grid>
<Grid.RowDefinitions>
<RowDefinition
Height="Auto" />
<RowDefinition
Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="100" />
<ColumnDefinition
Width="100" />
<ColumnDefinition
Width="100" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="0"
Grid.Row="0"
Content="First Name:" />
<Label
Grid.Row="1"
Content="Last Name:" />
<TextBox
Grid.Column="1"
Grid.Row="0"
Background="Yellow"
Margin="5"
FontWeight="Bold"
Text="{Binding Path=MyPerson.FirstName, Mode=OneWayToSource, ElementName=myWindow, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock
Grid.Column="2"
Text="{Binding Path=MyPerson.CheckFirstName, Mode=OneWay, ElementName=myWindow}"
/>
<TextBox
Grid.Column="1"
Grid.Row="1"
Background="Yellow"
Margin="5"
FontWeight="Bold"
Text="{Binding Path=MyPerson.LastName, Mode=OneWayToSource, ElementName=myWindow, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock
Grid.Column="2"
Grid.Row="1"
Text="{Binding Path=MyPerson.CheckLastName, Mode=OneWay, ElementName=myWindow}" />
</Grid>
</Window>
<TextBox Grid.Column="1" Grid.Row="0" Background="Yellow" Margin="5" FontWeight="Bold" Text="{Binding Path=FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock x:Name="stat1" Grid.Column="2" />
<TextBox x:Name="stat2" Grid.Column="1" Grid.Row="1" Background="Yellow" Margin="5" FontWeight="Bold" Text="{Binding Path=LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Grid.Column="2" Grid.Row="1" />