мы работаем целый день по этой проблеме, и все это подытожено до небольшого примера. В настоящее время мы конвертируем проект из 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 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();
}
Если вы начнете проект таким образом, текст Debug не будет содержать никакого текста. Если вы вызовете DoNothing() после InitializeComponent(), он отобразит текст. Может кто-нибудь объяснить, почему? Обратите внимание: в Silverlight оба способа работают. Кроме того, если вы не используете элемент управления в datatemplate, оба способа работы.
Это интересный побочный эффект. Это имеет смысл, если вы считаете, что регистрация DependencyProperty добавляет его в какую-либо глобальную коллекцию. Если сначала вызвать статический конструктор на MyAttachedProperty, он сначала добавляется в коллекцию и устанавливается сначала для объекта.
Если вы вынудите статический конструктор запускать сначала в MyControl, добавив тот же пустой статический метод DoNothing, то вы можете сделать
public MainWindow()
{
MyControl.DoNothing();
MyAttachedProperty.DoNothing();
InitializeComponent();
}
и текст будет показан или в случае
public MainWindow()
{
MyAttachedProperty.DoNothing();
MyControl.DoNothing();
InitializeComponent();
}
будет показан пустой текст.