Как я могу реализовать «сквозную» привязку данных? - PullRequest
0 голосов
/ 16 апреля 2009

Небольшая предыстория: Я загружаю пользовательский интерфейс WPF из базы данных, которая хранится в таблице свойств (тип элемента управления, метка, поле и т. Д.), Которую загружаю в класс, который я называю ControlPresenter , В основном я устанавливаю ControlPresenter как DataContext ContentPresenter и использую TemplateSelector, чтобы выбрать, какой тип элемента управления загрузить. DataTemplate (ы) загружают свои свойства из свойств DependencyProperties, предоставляемых ControlPresenter.

Это все работает очень хорошо. Проблема, с которой я сталкиваюсь, возникает, когда я пытаюсь привязать данные (например, свойство Text TextBox к свойству Name докладчика) в других докладчиках (которые имеют обычные свойства, реализующие INotifyPropertyChanged) с этими элементами управления. DataContext элемента управления является связанным ControlPresenter, поэтому я не могу привязать напрямую к другим докладчикам и не могу установить две привязки для одного свойства зависимости (я не могу привязать элемент управления и требуемое свойство докладчика к одному и тому же DP) ,

Возможные решения:

  1. Я мог бы преобразовать всех других докладчиков в использование DP (чрезвычайно трудоемкий и склонный вызывать проблемы с наследованием)
  2. Я мог бы использовать два DP для каждого свойства, через которое я хочу пройти, и попытаться связать их вместе с помощью измененных уведомлений

Оба они кажутся проблематичными и склонными к поломке, поэтому я надеюсь, что кто-то другой придумал лучшее решение.

Редактировать: Я нашел решение, которое работает довольно хорошо (см. Ниже). Спасибо всем, кто посмотрел на это, и если вы найдете лучший метод, чем я, пожалуйста, дайте мне знать.

Ответы [ 2 ]

0 голосов
/ 25 апреля 2009

В итоге я установил привязки в коде, установив Binding.Source для требуемой ViewModel, а затем используя путь в базе данных для Binding.Path. Я храню привязки в словаре (Of DependencyProperty, BindingBase), и когда загружается элемент управления, я использую BindingOperations.SetBinding, чтобы установить привязки для элемента управления. Кажется, это работает довольно хорошо, за исключением случайного порядка проблем с операциями (например, если вы установите SelectedItem / SelectedValue до ItemsSource, он будет установлен, но не будет отображаться в ComboBox).

0 голосов
/ 16 апреля 2009

Существует несколько способов доступа вне контекста DataContexts.

1) Связывание ElementName

Это, вероятно, наименее полезно, так как в большинстве сценариев реального мира то, что вы пытаетесь связать, в любом случае выходит за рамки имен. Но это способ доступа к параллельному или родительскому контексту данных, если элемент Framework находится в области имен.

<TextBox Text="{Binding ElementName=ControlSomewhereElseBoundToSomeOtherControlPresenter, Path=DataContext.SomeTextPropertyOnTheControlPresenter}" />

2) Связывание с относительным источником

Это похоже на # 1, но с использованием RelativeSource для перехода к соответствующему визуальному элементу и захвата DataContext. Конечно, это предполагает, что DataContext, который вы пытаетесь получить, находится выше того места, где вы в данный момент находитесь в дереве визуалов.

3) Использовать статическое реле

Вы можете представить свои альтернативные ControlPresenters в статическом классе, который действует как фасад для вашей ViewModel. Затем в каждом ViewModel создайте свойства экземпляра, которые проходят через статические методы / свойства. Это распространенный способ достижения общего хранилища в нескольких моделях просмотра. Я понимаю, что этот метод потребует от вас немного изменить шаблон, но добавление простой оболочки ViewModel вокруг этих классов «ControlPresenter» кажется намного более простым, чем описанные вами параметры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...