Проблемы с привязкой WPF, если не задан DataContext

Я успешно создал несколько UserControls с различными функциями, установив для DataContext в каждом элементе управления значение this. У меня всегда были проблемы при попытке разбить их на более мелкие «внутренние» UserControls, которые будут более удобными. Проблема вот в чем:

Когда для DataContext установлено значение this, я могу выполнить привязку к свойствам в коде позади - они не обязательно должны быть DependencyProperties. При привязке к обычным свойствам выполнение программы входит в код позади, где я могу делать такие вещи, как переключение элементов ListBox или другие вещи, которые я не могу делать в xaml.

Но когда я создаю новый «внутренний» UserControl, размещенный в исходном элементе управления, и перемещаю эти свойства во внутренний элемент управления, теперь мне нужно обновить их до DependencyProperties, чтобы я мог привязаться к ним из исходного элемента управления. При привязке к DependencyProperties выполнение программы никогда не входит в код позади, и для меня ЭТО проблема. Кстати, я не устанавливаю DataContext во внутреннем элементе управления, а вместо этого устанавливаю свойство Name корневого элемента и использую синтаксис ElementName = UserControlName в привязке свойств внутреннего элемента управления.

Я знаю, что могу добавить ValidateValueCallbackHandler в DependencyProperty, чтобы получить доступ к коду, стоящему за ним при изменении связанного значения, но это должен быть статический метод, поэтому я не могу получить доступ к нестатическим членам (т. Е. Ко всему моему классу) .

Одним из примеров является то, что у меня есть элемент управления DurationPicker, который отображает объекты TimeSegments в ListBoxes. Объекты TimeSegments в основном представляют собой ObservableCollection объектов TimeSegment, а TimeSegment имеет свойства StartDate, EndDate и Duration. У меня есть свойство MinutesPerSegment в элементе управления DurationPicker, которое было привязано к значениям из ComboBox. Это сработало отлично. Я мог бы изменить значение ComboBox, и код позади поместил бы правильное количество объектов TimeSegment с правильными новыми значениями в ListBox.

Затем я создал внутренний элемент управления, содержащий объект TimeSegments и ListBox для его отображения. Теперь свойство MinutesPerSegment должно было стать DependencyProperty, чтобы я мог привязаться к нему из внешнего элемента управления, и выполнение программы никогда не переходит в код позади, поэтому теперь я не могу изменить количество объектов TimeSegment в коллекции.

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

Как правильно это сделать? Большое спасибо.

РЕДАКТИРОВАТЬ. В этом примере, если я создаю объекты TimeSegments во внешнем элементе управления и привязываю их к внутреннему элементу управления, он все равно работает. Это связано с тем, что свойство MinutesPerSegment во внешнем элементе управления является обычным свойством ... Однако я хочу, чтобы каждый объект TimeSegments обрабатывался в его собственном внутреннем элементе управления TimeSegmentsRow ... и поэтому проблема.


person Sheridan    schedule 28.11.2010    source источник


Ответы (1)


Во-первых, вам не нужно устанавливать DataContext в this только для того, чтобы разрешить привязку к свойствам вашего настраиваемого элемента управления. Это плохая идея на случай, если кто-то решит установить другой контекст данных для вашего элемента управления. Вместо этого вы можете использовать относительную привязку.

{Binding Path=PathToProperty, 
         RelativeSource={RelativeSource AncestorType=
                         {x:Type namespaceAlias:typeOfYourControl}}}

и объявить псевдоним пространства имен для вашего настраиваемого элемента управления в xaml

xmlns:namespaceAlias="clr-namespace:YourLibraryNamespace;assembly=YourLibraryAssemblyName"

Во-вторых, wpf не будет использовать средства получения и установки свойств для доступа к свойствам зависимостей, поэтому не должно быть никакой дополнительной логики, кроме GetValue и SetValue. Вы можете указать PropertyChangedCallback при регистрации своего свойства, чтобы добавить некоторые логика при изменении собственности.

person alpha-mouse    schedule 28.11.2010
comment
Спасибо за подсказку о DataContext = this, но разве это не то же самое, что присвоить имя корневому элементу UserControl и использовать ElementName? Кроме того, делегат PropertyChangedCallback является статическим, как и ValidateValueCallback, поэтому я не могу получить доступ к членам класса оттуда. Вы говорите, что нет способа вызвать нестатический метод при изменении несвязанного свойства привязки к данным? - person Sheridan; 28.11.2010
comment
Статический метод PropertyChangedCallback получает DependencyObject в первом параметре. Это DependencyObject ваш элемент управления, поэтому вы можете привести его к своему типу элемента управления и использовать все члены. - person alpha-mouse; 28.11.2010
comment
Это было ТАК, что я искал! Большое спасибо! :) - person Sheridan; 29.11.2010