Как вы могли заметить, элементы управления ComboBox, ListBox и такого рода "селекторы" используют некоторые свойства с суффиксом "путь", который позволяет привязывать объекты с разными именами свойств к его шаблону данных без изменения самого шаблона.
Конечно, я не знаю точно, как называется эта техника, но в основном я пытаюсь получить что-то вроде этого:
<my:ACustomControl HeadingPath="SomePropertyOfModelA" ContentPath="OtherPropertyFromModelA" ItemsSource="{Binding ModelA}"... />
... и ничего не меняя в элементе управленияили его шаблон данных может это сделать
<my:ACustomControl HeadingPath="DifferentPropertyFromModelB" ContentPath="NewPropertyFromB" ItemsSource="{Binding ModelB}" ... />
Мне не очень нравится подход динамического построения таблицы данных с использованием конкатенации строк ...
Есть идеи?
РЕДАКТИРОВАТЬ:
ОК,
Это работает сейчас, но на моем подходе есть темное пятно.Поскольку я использую ValueConverters для получения фактического значения свойства, и этот преобразователь значений создается в Xaml как статический ресурс, я обнаружил, что при отображении usercontrol присутствует некоторый порядок приоритетов, поскольку ItemsControl получает данные элементов перед ValueConvertersполучает название собственности.В результате ничего не конвертируется.
Мой обходной путь заключался в том, чтобы принудительно установить значение PathProperty ValueConverter из кода сразу после установки значения HeadingPath.Вот почему статический ресурс имеет x: Name и x: Key.
Вот что я сделал до сих пор.(Пожалуйста, рассмотрите это как песочницу, извините за то, что не позаботились о соглашениях об именах и т. Д.)
1.- Создайте пользовательский элемент управления с ItemsControl внутри, например:
<ItemsControl x:Name="InternalItemsControl" ItemsSource="{Binding Items, Mode=TwoWay}">
Где Items - это свойство зависимости в коде, стоящем за
2.- Установите CodeBehind в качестве DataContext для usercontrol LayoutRoot Grid в конструкторе класса
Public Sub New()
InitializeComponent()
LayoutRoot.DataContext = Me
End Sub
3.- Определите свойство зависимости с именем Itemsв коде Позади
4.- Определите свойство зависимости с именем HeadingPath типа string для хранения имени свойства бизнес-объекта
5.- Создайте реализацию IVaueConverter, которая также наследуется от DependencyObject и реализует INotifyPropertyChanged следующим образом
Imports System.Windows.Data
Imports System.ComponentModel
Public Class PathPropertiesValueConverter
Inherits DependencyObject
Implements IValueConverter
Implements INotifyPropertyChanged
...
6.- Определите свойство зависимости внутри реализации IValueConverter с именем PathProperty типа string для хранения имени свойства, значение которого будет использоваться в качестве возвращаемого значения при преобразовании данных.
7.- При преобразовании метода ...:
Public Function Convert(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
If value IsNot Nothing AndAlso Not String.IsNullOrEmpty(PathProperty) Then
Return value.GetType.GetProperty(PathProperty).GetValue(value, Nothing)
Else
Return Nothing
End If
End Function
8.- Создание IValueConvошибочная реализация в качестве статического ресурса в usercontrol
<local:PathPropertiesValueConverter x:Key="PathConverter" x:Name="HeadingPathConverter"
PathProperty="{Binding ElementName=LayoutRoot, Path=DataContext.HeadingPath, Mode=TwoWay}" />
9.- После этого вы можете использовать имя свойства как строку в свойстве HeadingPath для привязки ChildItems к ItemsControl из любого silverlight Page:
<StackPanel Orientation="Vertical" >
<local:MyCustomControl HeadingPath="PropiedadA" Items="{Binding Listado, Mode=TwoWay}" />
<local:MyCustomControl HeadingPath="PropiedadB" Items="{Binding Listado2, Mode=TwoWay}" />
</StackPanel>
10. Быть Listado и Listado 2 ObservableCollections, загруженными данными и всем связующим материалом на этом уровне набора ... это результат:
http://dl.dropbox.com/u/6450273/PathProperties.JPG