#c# #wpf #attached-properties
#c# #wpf #прикрепленные свойства
Вопрос:
У меня есть простое присоединенное свойство:
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:
Когда свойство зависимости get / set через XAML, метод-оболочка никогда не вызывается. Итак, вам следует избегать написания кода там.
Из MSDN:
Текущая реализация WPF поведения процессора XAML для настройки свойств полностью обходит обертки, вам не следует добавлять какую-либо дополнительную логику в определения набора оболочки для вашего пользовательского свойства зависимостей. Если вы добавите такую логику в определение set, то логика не будет выполняться, если свойство задано в 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». «Привязка» может быть установлена только для DependencyProperty объекта DependencyObject.
Комментарии:
1. Но если я изменю имя на «TestProperty», то точка останова будет достигнута в
SetTest
2. @Aron — Нет, третий аргумент относится к типу владельца и поскольку это присоединенное свойство. Таким образом, владелец будет содержать класс. Так и должно быть
typeof(TestAttached)
.3. @RohitVats не могли бы вы также записать строку
TextBox tb = d as TextBox;
msmvps.com/blogs/jon_skeet/archive/2013/09/19 /…4. Я основывал это в основном на этом посте , откуда взялось большинство этого материала, но я также просто пытался создать SSCCE… Ну что ж
5. @Aron — Эта часть не имеет отношения к этому ответу, потому что OP интересуется, почему DP не работает.
Casting vs "as"
это совершенно другая тема. Пусть ссылка останется здесь в комментариях (очевидно, это может быть полезно для OP), чтобы ответ оставался точным для будущих читателей.