在自定义控件中模仿ItemsControl行为

时间:2011-04-24 22:18:32

标签: c# wpf xaml data-binding itemssource

我有课程标记

class Marker {
  public double Position {get; set;}
  public string Label {get; set;}
}

和自定义控件,除其他属性外,还公开标记集合

class MyControl {
  public ObservableCollection<Marker> Markers {get; set;}
}

我想模仿ItemsControl行为,并允许我的组件的用户直接或使用ItemsSource类比指定标记。此外,我想要两种方法来支持数据绑定(最好是在XAML中)

直接标记

<my:MyControl>
  <my:MyControl.Markers>
    <my:Marker Position="{Binding X}" />
  </my:MyControl.Markers>
</my:MyControl>

使用MarkersSource标记

<my:MyControl MarkersSource={Binding UserSpecifiedCollection}">
</my:MyControl>

第一种方法非常简单,但我在第二种方法上苦苦挣扎。

如何实施MarkesSource?如何将UserSpecifiedCollection项转换为Marker类型?如何将UserSpecifiedCollection项的属性数据绑定到Marker的属性?

关于转换我认为可以使用ValueConvertor,但我更喜欢纯XAML解决方案,比如DataTemplates。有可能的?

1 个答案:

答案 0 :(得分:0)

您需要绑定的依赖项属性,您可以使用DependencyProperty.AddOwner“回收”其他控件的属性,或者只创建自己的属性。此外,您可能希望将绑定从您的属性“转发”到内部ItemsControl或您使用的任何内容,例如。

<UserControl x:Class="Test.UserControls.MyUserControl3"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             Name="control">
    <Grid>
        <!-- Binds to the new property -->
        <ItemsControl ItemsSource="{Binding ElementName=control, Path=MarkersSource}"/>
    </Grid>
</UserControl>
public partial class MyUserControl3 : UserControl
{
    public static readonly DependencyProperty MarkersSourceProperty =
            DependencyProperty.Register("MarkersSource",
                                        typeof(ObservableCollection<Employee>),
                                        typeof(MyUserControl3),
                                        new UIPropertyMetadata(null));
    public ObservableCollection<Employee> MarkersSource
    {
        get { return (ObservableCollection<Employee>)GetValue(MarkersSourceProperty); }
        set { SetValue(MarkersSourceProperty, value); }
    }

    public MyUserControl3()
    {
        InitializeComponent();
    }
}

用法示例:

<uc:MyUserControl3 MarkersSource="{Binding DpData}">
    <uc:MyUserControl3.Resources>
        <DataTemplate DataType="{x:Type obj:Employee}">
            <TextBlock Text="{Binding Name}" Foreground="Red"/>
        </DataTemplate>
    </uc:MyUserControl3.Resources>
</uc:MyUserControl3>

这里我通过资源隐式应用DataTemplate,但您可以创建另一个属性(重用ItemsControl.ItemTemplate)并将其转发到内部ItemsControl。