Привязка к TreeView SelectedItem работает как ItemsSource, но не для пользовательского DependencyProperty - PullRequest
0 голосов
/ 08 октября 2019

У меня есть TreeView с ICollection <...> для его ItemsSource. Теперь я пытаюсь использовать SelectedItem в некоторых других элементах управления. По какой-то причине я могу правильно установить привязку, используя ElementName для ListView, но когда я пытаюсь реализовать то же самое для настраиваемого свойства DependencyProperty, он никогда не обновляется.

Вот XAML (ListView работает, а MyControl - нет). ):

<ListView ItemsSource="{Binding ElementName=myTreeView, Path=SelectedItem.Children}" />
<modules:MyControl Grid.Row="1" Blubbi="{Binding ElementName=myTreeView, Path=SelectedItem}" />

И DependencyProperty MyControl:

public static readonly DependencyProperty BlubbiProperty = DependencyProperty.Register(
    nameof(Blubbi), typeof(object), typeof(MyControl), new PropertyMetadata(default(object)));

public object Blubbi
{
    get => (object) GetValue(BlubbiProperty);
    set => SetValue(BlubbiProperty, value);
}

Я подозреваю, что что-то в реализации DependencyProperty неверно, но я не могу понять, что.

1 Ответ

1 голос
/ 09 октября 2019

Я не думаю, что с вашим свойством зависимости есть что-то технически неправильное, но оно также не выглядит особенно полезным при его реализации. Обычно при реализации свойства зависимостей вы хотите, чтобы что-то происходило, когда оно получает новое значение. Самый простой способ сделать это с помощью обратного вызова с измененным значением. Например:

public static readonly DependencyProperty BlubbiProperty = DependencyProperty.Register(
    nameof(Blubbi), typeof(object), typeof(MyControl),
    new PropertyMetadata(default(object), (d, e) => ((MyControl)d).OnBlubbiChanged(e.oldValue, e,newValue)));

private void OnBlubbiChanged(object oldValue, object newValue)
{
    // Do something here
}

Вы также можете выполнять более сложные действия в ответ на новые входящие значения, но обычно это не требуется. Если вы хотите прочитать больше, вот статья .

. Теперь все это хорошо для любого DependencyObject, но если вы - элемент, который простирается от FrameworkElement, чтобольшинство элементов делает, тогда вы можете использовать FrameworkPropertyMetadata вместо PropertyMetadata, который предоставляет некоторые дополнительные удобные функции в виде FrameworkPropertyMetadataOptions .

Итак, допустим, вы используетеэто свойство в OnRender переопределении вашего элемента, тогда вы можете убедиться, что рендер автоматически становится недействительным при каждом изменении значения свойства, так что OnRender будет вызываться снова.

public static readonly DependencyProperty BlubbiProperty = DependencyProperty.Register(
    nameof(Blubbi), typeof(object), typeof(MyControl),
    new FrameworkPropertyMetadata(default(object), FrameworkPropertyMetadataOptions.AffectsRender));

Более того, если ваш элемент является Control, который использует XAML-определенный шаблон для представления себя, тогда вы можете оставить свойство зависимости таким, как оно есть, и использовать его в своем шаблоне управления через TemplateBinding.

<ControlTemplate TargetType="{x:Type myNamespace:MyControl}">
    <TextBlock Text="{TemplateBinding Blubbi}" />
</ControlTemplate>

Так что, когдаВы говорите, что ваша собственность никогда не обновляется, я должен спросить, откуда вы это знаете? Предоставленный вами код неполон, но, похоже, вы на самом деле ничего не делаете со свойством, которое бы указывало на то, что оно изменилось.

В качестве дополнительного примечания, поскольку это часто удивляет людей, свойство, которое у вас естьопределенный для переноса вашего свойства зависимости, никогда не будет вызываться через привязку. Привязки используют систему объектов зависимостей для непосредственного обновления свойства зависимостей. Хотя для установки свойства из XAML требуется свойство-обертка, оно фактически не вызывается при работе со свойством зависимости. Другими словами, точка останова в установщике вашего свойства оболочки никогда не будет достигнута. Поэтому никогда не помещайте важную логику в свойство оболочки.


Редактировать: Если вы все еще пытаетесь выяснить, что идет не так, вы можете получить привязку для вывода отладочной информации в окно вывода вашего отладчика. установив для него TraceLevel присоединенное свойство равным High, вот так:

<modules:MyControl
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    Blubbi="{Binding ElementName=myTreeView, Path=SelectedItem, diag:PresentationTraceSources.TraceLevel=High}" />
...