silverlight - привязка к двум объектам - PullRequest
0 голосов
/ 03 мая 2011

Я хочу создать пользовательский элемент управления, который может быть связан с некоторыми данными, данными извне элемента управления (требование A), а некоторые свойства XAML должны быть связаны со свойствами самого элемента управления (требование B).

Допустим, у меня есть класс данных с именем StudentData и элемент управления с именем StudentControl. Я использую этот элемент управления внутри DataGrid. Я поместил StudentControl в сетку с помощью DataGridTemplateColumn. Я как-то привязываю StudentData в текущей ячейке к элементу управления. Это требование А. Этот StudentControl хочет указать, являются ли некоторые элементы управления внутри него редактируемыми или нет. Лучший способ сделать это - выставить свойство, например StudentControl.AreSomeControlsEditable. Затем я могу привязать свойство IsEnabled этих элементов управления к этому свойству. Это требование Б.

Вот моя первая идея. Я привязываю текущий StudentData к DP StudentControl, затем внутри StudentControl меняю контекст данных на сам элемент управления:

<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <TextBox
    Content="{Binding Path=ExposedStudentData.Field1}" *reqA*
    IsEnabled="{Binding Path=OtherProperty1}" /> *reqB*
</UserControl>

Таким образом, я полагал, что StudentControl получает StudentData извне, предоставляет те же данные StudentData и другие новые свойства (поэтому данные и другие свойства теперь находятся в одном месте, а не в двух), и затем я могу привязать их выставленные свойства в XAML (reqA + reqB выполняются одновременно). За исключением того, что это не работает из-за этой ошибки . По сути, если я установлю DataContext элемента управления на себя, он будет установлен до применения внешней привязки. Поэтому, если мой путь привязки внутри ячейки - X, а затем контекст данных изменяется, механизм привязки будет искать X в новом контексте собственных данных, а не во внешнем контексте данных сетки.

Вот моя вторая идея. Я привязываю текущий StudentData к DataContext или DP в StudentControl. Затем, чтобы получить доступ к другим открытым свойствам StudentControl, я даю имя UserControl и использую привязку ElementName:

<UserControl x:Name="self">
  <TextBox
    Content="{Binding Path=Field1}" *reqA*
    IsEnabled="{Binding ElementName=self, Path=OtherProperty1" /> *reqB*
</UserControl>

Таким образом, я решил, что текущий контекст данных - это StudentData, и он не изменился, и я могу привязать его к этому с помощью простого пути (reqA), а я могу привязать к другим предоставляемым свойствам с помощью элемента ElementName ( reqB). Он работает в базовых сценариях, но не в DataGrid из-за этой ошибки . Я предполагаю, что проблема возникает, когда в визуальном дереве есть несколько элементов управления с одинаковыми именами.

Я действительно начинаю ненавидеть Silverlight, я начал использовать его месяц назад и уже сообщил о 9 ошибках. Всякий раз, когда я пытаюсь достичь чего-то другого, кроме простого приложения hello world или чего-то, для чего Microsoft и все остальные, кажется, используют Silverlight, я сталкиваюсь с новой ошибкой. И что теперь, как бы вы связали класс данных, заданный извне элемента управления, и некоторые другие свойства, предоставляемые элементом управления одновременно? Без, конечно, установки привязок из кода (который я делаю сейчас, но это кошмар с ListBoxes и DataTemplates) или вообще не используется привязка.

Ответы [ 2 ]

1 голос
/ 03 мая 2011

Я думаю, что ваша проблема с DataContext и его наследованием, а также с именами .

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

Для вашей второй проблемы, если вы находитесь внутри DataTemplate, вы находитесь в другой области имен, чем за ее пределами. Вы не можете получить доступ к элементам управления «по имени» вне DataTemplate. Что вы можете сделать здесь (для Silverlight 4 и ниже), так это самостоятельно пройти по дереву визуалов и найти нужный элемент управления. Это, однако, станет намного проще и менее болезненным с некоторыми новыми функциями в SL5, в частности с функцией «FindAncestor» (которая уже существует в WPF).

Вот статья на MSDN о Namescopes в Silverlight . А вот еще один о DataBinding, который упоминает, как DataContext наследуется .

Чтобы достичь того, что вы ищете, я думаю это сообщение в блоге должно вам помочь. В нем показано, как реализовать привязку RelativeSource с FindAncestor в Silverlight.

Надеюсь, это поможет:)

0 голосов
/ 03 мая 2011

На другом форуме мне сказали использовать MVVM.Как оказалось, это может сделать мою первую идею немного лучше.Вместо привязки моего StudentControl к StudentData, а затем предоставления этих данных и других свойств, я должен создать модель представления, скажем StudentControlData, которая содержит StudentData и дополнительные свойства, необходимые для элемента управления.Если я привяжу к этому свой элемент управления, то в контексте унаследованных данных элемента управления у меня будет доступ ко всем необходимым мне свойствам.Теперь единственной проблемой остается то, что внутри ListBox в моем StudentControl я теряю этот контекст данных.

...