0

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

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

在此处输入图像描述

编辑1:

忘记在帖子中添加一行代码Ellipse el = nn.GetTemplateChild("PART_inner") as Ellipse;

编辑2:

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

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

编辑3:

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

在 OnApplyTemplate() 我添加

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

2 回答 2

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..
}
于 2013-05-30T01:50:42.920 回答
0

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

XAML 解析器通过 XAML 从上到下工作。UserControl 只是定义它的 XAML 的快捷方式,因此,当 XAML 解析器HasConnection=True在外部控件上设置时,它的内容还没有被实例化,因此 PART_Inner 还不存在。

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

其他选项是根本不使用DependencyPropertyChanged回调,而是使用RelativeSourcetypedFindAncestorBooleanToVisibilityConverter. 还有一个想法是使用Trigger.

于 2013-05-30T09:57:21.603 回答