具有默认值的依赖属性抛出StackOverflowException

时间:2012-02-24 14:15:29

标签: c# wpf wpf-controls dependency-properties

我正在使用WPF SQL Connection User Control。每当我在一个已打开,关闭然后再打开的选项卡(AvalonDock DocumentTab )上抛出 StackOverflowException 时,我遇到了一个问题。< / p>

我已经搞砸了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时,我没有遇到这个问题。对我来说,这说明问题在于依赖属性的默认值。

我在网上捅了一下,看看是否有其他人有这个问题,但似乎我可能已经让自己陷入了一些困境。我可以认为这个问题可能来自于this SO question about dependency properties which was answered as thread safety。我不确定依赖属性如何处理它们的默认值,但我可以看到,如果同一个对象连接了OnPropertyChanged事件的两倍问题。然而,这也让我相信,如果是这种情况,这个问题会在某个地方被注意到!

有什么想法吗?

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

3 个答案:

答案 0 :(得分:2)

每次关闭选项卡时,是否都会注册新的依赖项属性?我很确定如果它所引用的内容已被处理,你就不能重用相同的依赖属性注册。关闭选项卡后,垃圾收集器将尝试使用“ConnectionString”对象。当标签失去范围时,它将处理所有子变量,即使它们是静态只读。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

可能,添加

if (value != GetValue(ConnectionStringProperty))
设置者中的

会阻止它。