Поведение Mimic ItemsControl в пользовательском элементе управления - PullRequest
0 голосов
/ 25 апреля 2011

У меня есть класс Marker

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 могут быть преобразованы в тип маркера?Каким образом свойства элементов UserSpecifiedCollection могут быть привязаны к свойствам маркера на основе данных?

Относительно преобразования Я думаю, что можно использовать ValueConvertor, но я бы предпочел чистое решение XAML, что-то вроде DataTemplates.Это возможно?

1 Ответ

0 голосов
/ 25 апреля 2011

Вам нужны свойства зависимостей для привязок, вы можете «перерабатывать» свойства других элементов управления с помощью 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.

...