WPF: ItemsControl и DataContext - PullRequest
       40

WPF: ItemsControl и DataContext

3 голосов
/ 08 февраля 2010

У меня есть главное окно с единственным пользовательским элементом управления, которое называется SuperMode. SuperMode состоит из коллекции людей, и у каждого человека в этой коллекции есть своя собственная коллекция заданий. Звучит просто, верно?

Из файла SuperMode.xaml:

<UserControl 
    x:Class="Prototype.SuperMode"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Prototype"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"> <!-- NOTE! -->
    <!-- Look at how I'm setting the DataContext, as I think it's
         important to solve the problem! -->

    <ScrollViewer CanContentScroll="True">
        <ItemsControl ItemsSource="{Binding People}" Margin="1">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Rows="1"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </ScrollViewer>

</UserControl>

Это прекрасно работает, и я могу видеть четырех людей, как я ожидаю! Теперь все, что мне нужно сделать, это настроить XAML для пользовательского элемента управления Person, чтобы все его задачи также отображались.

Как видите, я использую свойство People для заполнения элемента управления элементами. Свойство People имеет тип ObservableCollection<Person>, где Person - другой пользовательский элемент управления как таковой ...

С Person.xaml:

<UserControl 
    x:Class="Prototype.Person"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Prototype">

    <Border Background="Black" CornerRadius="4" Margin="1">
        <ItemsControl ItemsSource="{Binding Tasks}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </Border>

</UserControl>

Tasks здесь есть свойство Person с типом ObservableCollection<Task>. Вот где он застревает! Очевидно, WPF не может найти какое-либо свойство Tasks и, глядя на окно вывода VS2008, я обнаружил следующее:

System.Windows.Data Ошибка: 39: Ошибка пути BindingExpression: свойство 'Tasks' не найдено в 'object' '' SuperMode '(Name =' SuperMode ')'. BindingExpression: Path = Задачи; DataItem = 'SuperMode' (Name = 'SuperMode'); Целевым элементом является «ItemsControl» (Name = ''); Свойство target - «ItemsSource» (тип «IEnumerable»)

Теперь я потерялся. Кажется, мне нужно установить атрибут DataContext для каждого Person, в противном случае он все равно будет думать, что контекст данных равен SuperMode, но как мне это сделать?

1 Ответ

4 голосов
/ 08 февраля 2010

Игнорируя довольно неприятный дизайн (вы должны взглянуть на MVVM), вы должны установить DataContext для дочерних UserControl с следующим образом:

<ItemsControl ItemsSource="{Binding People}" Margin="1">
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="FrameworkElement.DataContext" Value="{Binding RelativeSource={RelativeSource Self}}"/>
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Rows="1"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
...