在用户控件中实现自定义“路径”属性

时间:2012-02-16 18:02:18

标签: silverlight binding user-controls path

您可能已经注意到,ComboBox,ListBox和那种“选择器”控件使用一些带有后缀“path”的属性,该属性允许将具有不同属性名称的对象绑定到其datatemplate而不更改模板本身。

当然我不确切知道这种技术的名称,但基本上,我想要得到的是这样的:

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

...并且无需更改控件或其数据模板中的任何内容即可执行此操作

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

我真的不喜欢使用字符串连接动态构建datatemplate的方法......

有什么想法吗?

编辑:

行,

它现在正在运作,但我的方法有一些黑点。由于我使用ValueConverters获取属性的实际值,并且此值转换器在Xaml中实例化为静态资源,因此我发现在显示usercontrol时会涉及一些优先级顺序,因为ItemsControl在ValueConverters之前接收Items数据获取属性的名称。结果没有任何东西被转换。

我的解决方法是在设置HeadingPath的值后立即强制从后面的代码设置ValueConverter的PathProperty值。这就是为什么静态资源有x:Name和x:Key。

这是我到目前为止所做的。 (请将此视为沙盒,我很抱歉没有处理命名约定等等)

1.-使用ItemsControl创建一个自定义控件,如下所示:

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

其中Items是代码隐藏的依赖属性

2.-在类构造函数中将CodeBehind设置为usercontrol LayoutRoot Grid的DataContext

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

3.-在代码Behind

中定义名为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.-在Convert方法......:

    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.-将IValueConverter实现实例化为usercontrol中的静态资源

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

9.-在此之后,您可以在HeadingPath属性中使用Property Name作为字符串,以从任何silverlight页面绑定ItemsControl上的ChildItems:

    <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

1 个答案:

答案 0 :(得分:0)

我认为您最好的选择是自己创建DataTemplate。幕后DisplayMemberPath基本上是创建一个DataTemplate,其中TextBlock绑定到该属性。 SelectedValuePath只是一个带有PropertyChangedCallback的DependencyProperty,用于设置选定的值绑定路径。最终,您创建的任何自定义属性都将成为您在其他位置定义的某些功能的快捷方式。