当调用附加属性'类中的方法时,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注册将其添加到某个全局集合中时,这是有意义的。如果你先调用MyAttachedProperty的静态构造函数,它会首先被添加到集合中,并首先为对象设置。
如果你通过添加相同的空静态方法DoNothing来强制静态构造函数首先在MyControl上运行,那么你可以执行
public MainWindow()
{
MyControl.DoNothing();
MyAttachedProperty.DoNothing();
InitializeComponent();
}
和文本将被显示或者
public MainWindow()
{
MyAttachedProperty.DoNothing();
MyControl.DoNothing();
InitializeComponent();
}