Значение DependencyProperty равно нулю, когда вызывается метод в классе присоединенного свойства

1

мы работаем целый день по этой проблеме, и все это подытожено до небольшого примера. В настоящее время мы конвертируем проект из 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, оба способа работы.

  • 1
    Я не могу дать вам объяснение, почему именно так себя ведет. Однако, кажется неправильным ожидать, что свойство Text имеет значение в первую очередь. Afaik WPF не гарантирует какой-либо порядок выполнения присваивания свойств в XAML.
Теги:
xaml
wpf
datatemplate

1 ответ

1
Лучший ответ

Это интересный побочный эффект. Это имеет смысл, если вы считаете, что регистрация DependencyProperty добавляет его в какую-либо глобальную коллекцию. Если сначала вызвать статический конструктор на MyAttachedProperty, он сначала добавляется в коллекцию и устанавливается сначала для объекта.

Если вы вынудите статический конструктор запускать сначала в MyControl, добавив тот же пустой статический метод DoNothing, то вы можете сделать

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

и текст будет показан или в случае

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

будет показан пустой текст.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню