Присоединенное свойство не работает, если я не поставлю "Свойство" в конце его имени

У меня есть простое прикрепленное свойство:

class TestAttached
{
    public static readonly DependencyProperty TestProperty = DependencyProperty.RegisterAttached("TestProperty", typeof(string), typeof(TestAttached));

    public static string GetTest(DependencyObject d)
    {
        return (string)d.GetValue(TestProperty);
    }

    public static void SetTest(DependencyObject d, string value)
    {
        d.SetValue(TestProperty, value);
        TextBox tb = d as TextBox;
        tb.Text = value;
    }
}

а также

<TextBox local:TestAttached.Test="Test" />

Ничего не происходит, и ни одна точка останова не достигнута SetTest) если я не установил первый параметр RegisterAttached "TestProperty" вместо "Test". Ни один учебник, который я нашел, в том числе и по MSDN, этого не делает, и, насколько я могу судить, мой код такой же, как у них, и должен работать. Что дает?

1 ответ

Решение

Когда свойство Dependency устанавливается / устанавливается через XAML, метод-обертка никогда не вызывается. Таким образом, вы должны избегать написания кода там.

Из MSDN:

Текущая реализация WPF поведения процессора XAML для установки свойств полностью обходит оболочки, вам не следует помещать какую-либо дополнительную логику в определения набора оболочек для вашего пользовательского свойства зависимости. Если вы поместите такую ​​логику в определение набора, то эта логика не будет выполняться, когда свойство задано в XAML, а не в коде.

Вместо этого вы можете использовать PropertyChangedCallback в случае, если вы хотите поместить некоторый код на изменение свойства DP.

public static readonly DependencyProperty TestProperty =
    DependencyProperty.RegisterAttached("Test", typeof(string),
                                         typeof(TestAttached),
                                         new PropertyMetadata(TestChanged));

public static void TestChanged(DependencyObject d,
                               DependencyPropertyChangedEventArgs e)
{
    // Place your code here
}

ОБНОВИТЬ

Но если я изменю имя на "TestProperty", то точка останова попадет в SetTest.

Причина этого заключается в следующем: Test теперь ведет себя как обычное свойство CLR. Свойство - это не что иное, как методы Get/Set, когда вы переходите к IL-коду.

Вот почему сеттер получает удар, как и для обычного свойства CLR.

Если вы попытаетесь связать с каким-либо другим свойством,

<TextBox local:TestAttached.Test="{Binding SomeCLRProperty}" />

вы увидите сбой приложения, заявив:

"Связывание" не может быть установлено в свойстве "SetTest" типа "TextBox". "Связывание" может быть установлено только для свойства DependencyObject объекта DependencyObject.

Другие вопросы по тегам