当调用附加属性'类中的方法时,DependencyProperty'的值为null

本文关键字:null 方法 DependencyProperty 调用 属性 | 更新日期: 2023-09-27 18:09:02

我们花了整整一天的时间来研究这个问题,并把它总结为一个小例子。我们目前正在将一个项目从Silverlight转换为WPF,在Silverlight中两个版本都可以工作,而在WPF中只有一个可以。

我们有一个简单的控件,它有一个字符串类型的依赖属性,像这样:

public class MyControl : Control
{
  public String Text
  {
    get { return (String)GetValue(TextProperty); }
    set { SetValue(TextProperty, value); }
  }
  public static readonly DependencyProperty TextProperty =
    DependencyProperty.Register("Text", typeof(String), typeof(MyControl), new PropertyMetadata(null, TextChanged));
  private static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
  }
}

那么我们就有了一个带有如下附加属性的类:

public class MyAttachedProperty
{
  public static readonly DependencyProperty DescriptionProperty = DependencyProperty.RegisterAttached("Description", typeof(String), typeof(MyAttachedProperty), new PropertyMetadata(null, DescriptionPropertyChanged));
  public static String GetDescription(DependencyObject obj, String value)
  {
    return (String)obj.GetValue(DescriptionProperty);
  }
  public static void SetDescription(DependencyObject obj, String value)
  {
    obj.SetValue(DescriptionProperty, value);
  }
  private static void DescriptionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    var MySuperbControl = d as MyControl;
    Debug.WriteLine("The control's text is: " + MySuperbControl.Text);
  }
  public static void DoNothing()
  {
  }
}

我们在MainWindow中实现了这样的控件。xaml:

<ContentControl x:Name="MyContentControl">
  <ContentControl.ContentTemplate>
    <DataTemplate>
      <local:MyControl x:Name="MyCntrl" Text="DefaultText" att:MyAttachedProperty.Description="Test"/>
    </DataTemplate>
  </ContentControl.ContentTemplate>
</ContentControl>

和后面代码中的构造函数:

public MainWindow()
{
  MyAttachedProperty.DoNothing();
  InitializeComponent();
}

如果以这种方式启动项目,则调试文本将不包含任何文本。如果在InitializeComponent()之后调用DoNothing(),它将显示文本。有人能解释一下为什么吗?注意,在Silverlight中这两种方式都可以工作。另外,如果不在数据模板中使用控件,两种方法都可以使用。

当调用附加属性'类中的方法时,DependencyProperty'的值为null

这是个有趣的副作用。当您认为DependencyProperty注册将其添加到某个全局集合中时,这是有意义的。如果你先调用MyAttachedProperty的静态构造函数,它会首先被添加到集合中,并首先为对象设置。

如果你通过添加相同的空静态方法DoNothing来强制静态构造函数首先在MyControl上运行,那么你可以执行

    public MainWindow()
    {
        MyControl.DoNothing();
        MyAttachedProperty.DoNothing();
        InitializeComponent();
    }

和文本将被显示或者

    public MainWindow()
    {
        MyAttachedProperty.DoNothing();
        MyControl.DoNothing();
        InitializeComponent();
    }