简单的 WPF 数据绑定导致 StackOverFlow 异常
simple WPF data binding results in StackOverFlow exception
我的 WPF 项目中有以下 XAML:
<Window x:Class="DataBindToLocalVars.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox x:Name="txt2" HorizontalAlignment="Left" Height="23" Margin="150,94,0,0" TextWrapping="Wrap" Text="{Binding Path=value1}" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="txt1" HorizontalAlignment="Left" Height="23" Margin="150,140,0,0" TextWrapping="Wrap" Text="{Binding Path=value2}" VerticalAlignment="Top" Width="120"/>
<Label Content="Value 2" HorizontalAlignment="Left" Margin="107,91,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.577,-0.602"/>
<Label Content="Value1" HorizontalAlignment="Left" Margin="107,145,0,0" VerticalAlignment="Top"/>
</Grid>
以及我的代码隐藏文件中的以下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 DataBindToLocalVars
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string value1
{
get { return value1; }
set
{
value1 = value;
this.NotifyPropertyChange("value1");
}
}
public string value2 {
get { return value2; }
set {
value2 = value;
this.NotifyPropertyChange("value2");
} }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
value1 = "20";
value2 = "40";
}
public void NotifyPropertyChange(string propName)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
我正在实现 INotifyPropertyChange 接口,以便在属性 value1 和 value2 更改时得到通知。但是 运行 这段代码给了我一个堆栈溢出异常。这是为什么?
当然是你在属性中设置了属性
您需要在 属性 中设置一个私有成员,然后您提高 属性 更改,以便通知绑定对象对其进行采样。
首先请使用大写字母。
private int _value1;
public int Value1
{
get{ return _value1; }
set
{
_value1 = value;
NotifyPropertyChange("Value1");
}
}
编辑:
您 运行 使用的 .Net 版本是什么?
我记得 .net 4 中的一个问题,你必须这样做。
public event PropertyChangedEventHandler PropertyChanged = delelgate{};
因此在绑定订阅之前事件不会为空。
这是你的事业:
public string value1
{
get { return value1; }
set
{
value1 = value;
this.NotifyPropertyChange("value1");
}
}
您的 属性 getter 和 setter 是完全递归的(它们会导致对自身的调用)。
地道的 C# 使用 PascalCasing 作为 属性 名称,那么如何:
private string value1;
public string Value1
{
get { return value1; }
set
{
value1 = value;
this.NotifyPropertyChange("Value1");
}
}
此处 getter 和 setter 使用私有 value1
字段。
您的 INotifyPropertyChanged
实施也有问题。当事件没有订阅者时,处理程序将为 null
。你需要提防这个,否则你会得到 NullReferenceException
:
public void NotifyPropertyChange(string propName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propName));
}
我的 WPF 项目中有以下 XAML:
<Window x:Class="DataBindToLocalVars.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox x:Name="txt2" HorizontalAlignment="Left" Height="23" Margin="150,94,0,0" TextWrapping="Wrap" Text="{Binding Path=value1}" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="txt1" HorizontalAlignment="Left" Height="23" Margin="150,140,0,0" TextWrapping="Wrap" Text="{Binding Path=value2}" VerticalAlignment="Top" Width="120"/>
<Label Content="Value 2" HorizontalAlignment="Left" Margin="107,91,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.577,-0.602"/>
<Label Content="Value1" HorizontalAlignment="Left" Margin="107,145,0,0" VerticalAlignment="Top"/>
</Grid>
以及我的代码隐藏文件中的以下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 DataBindToLocalVars
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string value1
{
get { return value1; }
set
{
value1 = value;
this.NotifyPropertyChange("value1");
}
}
public string value2 {
get { return value2; }
set {
value2 = value;
this.NotifyPropertyChange("value2");
} }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
value1 = "20";
value2 = "40";
}
public void NotifyPropertyChange(string propName)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
我正在实现 INotifyPropertyChange 接口,以便在属性 value1 和 value2 更改时得到通知。但是 运行 这段代码给了我一个堆栈溢出异常。这是为什么?
当然是你在属性中设置了属性 您需要在 属性 中设置一个私有成员,然后您提高 属性 更改,以便通知绑定对象对其进行采样。
首先请使用大写字母。
private int _value1;
public int Value1
{
get{ return _value1; }
set
{
_value1 = value;
NotifyPropertyChange("Value1");
}
}
编辑:
您 运行 使用的 .Net 版本是什么? 我记得 .net 4 中的一个问题,你必须这样做。
public event PropertyChangedEventHandler PropertyChanged = delelgate{};
因此在绑定订阅之前事件不会为空。
这是你的事业:
public string value1
{
get { return value1; }
set
{
value1 = value;
this.NotifyPropertyChange("value1");
}
}
您的 属性 getter 和 setter 是完全递归的(它们会导致对自身的调用)。
地道的 C# 使用 PascalCasing 作为 属性 名称,那么如何:
private string value1;
public string Value1
{
get { return value1; }
set
{
value1 = value;
this.NotifyPropertyChange("Value1");
}
}
此处 getter 和 setter 使用私有 value1
字段。
您的 INotifyPropertyChanged
实施也有问题。当事件没有订阅者时,处理程序将为 null
。你需要提防这个,否则你会得到 NullReferenceException
:
public void NotifyPropertyChange(string propName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propName));
}