具有默认值的依赖项属性引发StackOverflowException

本文关键字:属性 StackOverflowException 依赖 默认值 | 更新日期: 2023-09-27 18:25:45

我正在使用WPF SQL连接用户控件。每当我在选项卡(AvalonDockDocumentTab)上打开、关闭并再次打开它时,它就会抛出StackOverflowException

为了更好地适应我的应用程序,我对Jake的基本实现进行了修改,但本质上是一样的。我添加了一个禁用数据库选择的属性。

我已经将控件放入我的应用程序中,如下所示:

<controls:SqlConnectionStringBuilder
       Grid.Row="2"
       Margin="0,10,0,0"
       ConnectionString="{Binding ElementName=listBoxClients,
                                  Path=SelectedItem.ConnectionString,
                                  UpdateSourceTrigger=PropertyChanged}"
       Header="Connection String"
       RequireDatabase="True" />

为了解决这个问题,我对SqlConnectionStringBuilder的代码进行了一些重构,但这似乎是有问题的代码:

public static readonly DependencyProperty ConnectionStringProperty =
    DependencyProperty.Register(
        "ConnectionString", 
        typeof(SqlConnectionString),
        typeof(SqlConnectionStringBuilder),
        new FrameworkPropertyMetadata(
            new SqlConnectionString { IntegratedSecurity = true, Pooling = false },
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public SqlConnectionString ConnectionString
{
    get { return (SqlConnectionString)GetValue(ConnectionStringProperty); }
    set { SetValue(ConnectionStringProperty, value); }
}

在选项卡的第二次打开时,SqlConnectionString对象通过其OnPropertyChanged方法和IntegratedSecurity属性进入一个无限循环。当我使ConnectionString属性不是DependencyProperty时,我不会遇到这个问题。对我来说,这说明问题出在依赖属性的默认值上。

我在网上闲逛,看看是否有其他人有这个问题,但似乎我自己也陷入了困境。我认为这个问题可能来自于关于依赖属性的SO问题,这个问题被回答为线程安全。我不确定依赖属性如何处理它们的默认值,但我可以看到,如果同一个对象连接了两次OnPropertyChanged事件的问题。然而,这也让我相信,如果是这样的话,这个问题会在某个地方被注意到!

有什么想法吗?

其他信息
我从依赖属性的注册中删除了默认值(将其设置为null)。这样可以防止问题发生。此解决方案的唯一缺点是UI处于null状态,没有默认选择。不过,我想通过解决这个问题来防止这种情况发生。

具有默认值的依赖项属性引发StackOverflowException

是否在每次选项卡关闭时都注册新的依赖属性?我确信,如果引用的内容已被处理,则不能重用相同的依赖属性注册。一旦您关闭选项卡,垃圾收集器将尝试吃掉您的"ConnectionString"对象。当选项卡失去作用域时,它将处理所有子变量,即使它们是静态只读的。

在那个无限循环中,谁在为IntegratedSecurity属性赋值以响应OnPropertyChanged?如果你发现那是谁,这就是你答案的关键。

可能,添加

if (value != GetValue(ConnectionStringProperty))

在setter中将停止它。