依赖属性PropertyChangedCallback异常

时间:2013-05-30 01:25:45

标签: c# .net wpf xaml dependency-properties

我在自定义控件中有以下DependencyProperty

  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..
    }

运行正常,但是如果我在自定义控件的“属性”面板中更改属性,则在运行时抛出异常:对象引用未设置为对象的实例。

enter image description here

EDIT1:

忘记在帖子Ellipse el = nn.GetTemplateChild("PART_inner") as Ellipse;

中添加一行代码

EDIT2:

创建BooleanToVisibilityConverter并在Generic.xaml中使用Binding有效,但HasConnectionChangedCallBack方法现在为空/无用。

Visibility="{Binding HasConnection, Converter={StaticResource BooleanToVisibiltyConverter}, RelativeSource={RelativeSource TemplatedParent}}"

EDIT3:

找到了一个可行的解决方案。首先调用属性回调方法,然后调用OnApplyTemplate()方法,因此不再抛出异常或xaml中出现错误。

在OnApplyTemplate()中我添加

 if (this.HasConnection)
            PART_inner.Visibility = System.Windows.Visibility.Visible;
        else
            PART_inner.Visibility = System.Windows.Visibility.Hidden;

2 个答案:

答案 0 :(得分:0)

这样做

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..
}

答案 1 :(得分:0)

异常的原因是当通过XAML解析器设置属性时,UserControl的内容尚未实例化。

XAML解析器通过XAML从上到下运行。 UserControl只是定义它的XAML的快捷方式,因此,当XAML解析器在外部控件上设置HasConnection=True时,其内容尚未实例化,因此PART_Inner尚不存在。 / p>

解决方案是以一种保持实例化序列的方式定义HasConnection与UserControl中依赖它的任何关系。例如,如果PART_Inner是UserControl,则可以在其Loaded事件中搜索其类型为NetworkNode的父级,以便可以评估HasConnection。这可能是需要对现有代码进行最少更改的解决方案。保留更改处理程序,包括安全代码,并将逻辑添加到包含的控件中,该控件从其祖先读取起始值。

其他选项可能是根本不使用DependencyPropertyChanged回调,而是使用RelativeSource键入的FindAncestorBooleanToVisibilityConverter在Visibility属性上创建Binding。另一个想法是使用Trigger