C# 依赖项属性PropertyChangedCallback异常

C# 依赖项属性PropertyChangedCallback异常,c#,.net,wpf,xaml,dependency-properties,C#,.net,Wpf,Xaml,Dependency Properties,我在自定义控件中具有以下dependencProperty: public bool HasConnection { get { return (bool)GetValue(HasConnectionProperty); } set { SetValue(HasConnectionProperty, value); } } public static readonly DependencyProperty HasConnectionP

我在自定义控件中具有以下
dependencProperty

  public bool HasConnection
    {
        get { return (bool)GetValue(HasConnectionProperty); }
        set { SetValue(HasConnectionProperty, value); }
    }

    public static readonly DependencyProperty HasConnectionProperty =
        DependencyProperty.Register(
        "HasConnection",
        typeof(bool),
        typeof(NetworkNode),
        new FrameworkPropertyMetadata(
            false,
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
            new PropertyChangedCallback(HasConnectionChangedCallBack)));


    private static void HasConnectionChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        NetworkNode nn = (NetworkNode)d;
        Ellipse el = nn.GetTemplateChild("PART_inner") as Ellipse;
        if (el.PART_inner.Visibility == ...) <-- exception el is null
            //..code..
    }
编辑3:

找到了一个可能的解决办法。首先调用属性回调方法,然后调用OnApplyTemplate()方法,因此不会在xaml中引发更多异常或错误

在OnApplyTemplate()中,我添加了

这样做

private static void HasConnectionChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue == null) 
        return;

    NetworkNode nn = (NetworkNode)d;

    if (nn == null || nn.Part_inner == null ) 
        return;

    if (nn.PART_inner.Visibility == ...) <-- exception
        //..code..
}
私有静态void HasConnectionChangedCallBack(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
如果(e.NewValue==null)
返回;
网络节点nn=(网络节点)d;
如果(nn==null | | nn.Part_inner==null)
返回;

如果(nn.PART_internal.Visibility==…)出现异常的原因是,当通过XAML解析器设置属性时,UserControl的内容尚未实例化

XAML解析器通过XAML自上而下地工作。UserControl只是定义它的XAML的快捷方式,因此,当XAML解析器在外部控件上设置
HasConnection=True
时,其内容尚未实例化,因此内部部分还不存在

解决方案是在UserControl中定义HasConnection和依赖于它的任何对象之间的关系,这种定义方式要记住实例化顺序。例如,如果PART_Inner是UserControl,则可以在其加载的事件中搜索其NetworkNode类型的父对象,这样就可以计算
HasConnection
s可能是需要对现有代码进行最少更改的解决方案。保持更改处理程序不变,包括安全代码,并向包含的控件添加逻辑,该控件从其祖先读取起始值


其他选项是根本不使用
DependencyPropertyChanged
回调,而是使用
RelativeSource
键入的
FindAncestor
BooleantVisibilityConverter
在Visibility属性上创建绑定。还有一个想法是使用
触发器
,我认为没有这里的gh信息可以真正回答您的问题。什么是网络节点?什么是PART_Inner?它是一个自定义控件。如果我不接触wpf应用程序中的属性,则运行正常。如果设置HasConnection=“True”,在xaml中,在运行时抛出一个异常。我已经完成了
if(nn.Template!=null){…code here..}
,但我希望它能从一开始就工作。当我设置HasConnection=“True”时,自定义控件会更改。我猜生成没有成功。请重新生成您的程序。生成很好,没有错误,但在xaml中显示错误,请查看我的帖子图片。如果我运行应用程序,会引发异常。绑定工作
可见性=”{Binding HasConnection,Converter={StaticResource BooleantoVisibilityConverter},RelativeSource={RelativeSource TemplatedParent}”
。有没有办法让它从代码开始工作?好吧,你可以按照我对PART_Inner Loaded事件的建议,也可以对自定义控件的Loaded事件执行。在Loaded事件中,所有控件及其内容都保证被初始化。但是如果绑定工作,为什么要这样做呢?绑定或触发器是首选d处理这种情况的方法。只是想了解一下,在互联网上的所有示例中,我都看到了ChangedCallback方法中的逻辑。在依赖项属性描述中,它添加了deginer支持。如果我编辑nn属性,DP可以工作,但child为null。此外,该属性在用户控件中也可以正常工作
 if (this.HasConnection)
            PART_inner.Visibility = System.Windows.Visibility.Visible;
        else
            PART_inner.Visibility = System.Windows.Visibility.Hidden;
private static void HasConnectionChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue == null) 
        return;

    NetworkNode nn = (NetworkNode)d;

    if (nn == null || nn.Part_inner == null ) 
        return;

    if (nn.PART_inner.Visibility == ...) <-- exception
        //..code..
}