0
votes

As you might noticed, ComboBox, ListBox and that kind of "selectors" controls uses some properties with the suffix "path" which allows the binding of objects with different property names to its datatemplate without changing the template itself.

Certainly I don't know exactly the name of this technique, but Basically, what I'm trying to get is something like this:

<my:ACustomControl HeadingPath="SomePropertyOfModelA" ContentPath="OtherPropertyFromModelA" ItemsSource="{Binding ModelA}"... />

... and without changing anything in the control or its data template being able to do this

<my:ACustomControl HeadingPath="DifferentPropertyFromModelB" ContentPath="NewPropertyFromB" ItemsSource="{Binding ModelB}" ... />

I' dont really like the approach of building dynamically the datatemplate using strings concatenation...

Any ideas?

EDIT:

OK,

It's working now, but there is some dark spot on my approach. Since I'm using ValueConverters to get the actual value of the property, and this value converter is instantiated in Xaml as Static Resource, I've found that there's some priority order involved when the usercontrol is being shown since ItemsControl Receives Items data before ValueConverters gets the name of the property. As result nothing gets converted.

My workaround was to force setting ValueConverter's PathProperty Value from code behind right after setting HeadingPath's value. That's why the static resource has x:Name and x:Key.

Here is what I've done so far. (Please consider this as a sandbox, I'm sorry for not taking care of naming conventions and so on)

1.- Create a Custom Control With an ItemsControl inside like this:

<ItemsControl x:Name="InternalItemsControl" ItemsSource="{Binding Items, Mode=TwoWay}">

Where Items is a dependency property in code behind

2.- Set CodeBehind as DataContext of usercontrol LayoutRoot Grid at the class constructor

Public Sub New()
    InitializeComponent()
    LayoutRoot.DataContext = Me 
End Sub

3.- Define a dependency property named Items in code Behind

4.- Define a dependency property named HeadingPath of type string to hold business object property name

5.- Create a IVaueConverter Implementation which also inherits from DependencyObject and implements INotifyPropertyChanged like this

Imports System.Windows.Data
Imports System.ComponentModel

Public Class PathPropertiesValueConverter
    Inherits DependencyObject
    Implements IValueConverter
    Implements INotifyPropertyChanged
    ...

6.- Define a dependency property inside IValueConverter implementation named PathProperty of type string to hold the name of the property which value will be used as return value when converting data.

7.- At Convert method...:

    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.- Instantiate the IValueConverter implementation as static resource in usercontrol

<local:PathPropertiesValueConverter x:Key="PathConverter" x:Name="HeadingPathConverter" 
    PathProperty="{Binding ElementName=LayoutRoot, Path=DataContext.HeadingPath, Mode=TwoWay}" />

9.- After this you can use Property Name as string in HeadingPath property to bind ChildItems on ItemsControl from any 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.- Being Listado and Listado 2 ObservableCollections, loaded with data and all the binding stuff at this level set... this is the result:

http://dl.dropbox.com/u/6450273/PathProperties.JPG

1

1 Answers

0
votes

I think your best option will be to create the DataTemplate yourself. Behind the scenes DisplayMemberPath is basically creating a DataTemplate with a TextBlock bound to the property. SelectedValuePath is just a DependencyProperty with a PropertyChangedCallback that sets the selected value binding path. Ultimately any custom property you create is just going to be a shortcut to some functionality you've defined elsewhere.