ListBox ItemTemplate непостоянен с данными CLR и UserControl - PullRequest
1 голос
/ 22 июля 2010

Я написал простой UpDown UserControl для своего приложения.Я рендерил его в ListBox, чтобы при добавлении элементов управления UpDown они складывались горизонтально.

В моем UserControl есть один DependencyProperty, соответствующий номеру внутри элемента управления UpDown, который называется NumberProperty.

Я добавляю несколько элементов управления UpDown в ListBox через привязку данных, где ItemsSource для ListBox - это просто ObservableCollection<NumberGroup>, называемый NumberGroups.Каждый NumberGroup просто имеет элемент с именем Number, и я хочу, чтобы этот номер отображался в соответствующем элементе управления UpDown при визуализации ListBox.

Мой ListBox определен в XAML следующим образом:

    <ListBox Grid.Row="1" ItemsSource="{Binding NumberGroups}" ItemTemplate="{StaticResource NumberGroupTemplate}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" Width="Auto" Height="Auto" />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

и DataTemplate для ListBox:

    <DataTemplate x:Key="RackTemplate">
        <StackPanel Orientation="Vertical">
            <TextBlock>Group</TextBlock>
            <updown:UpDown Number="{Binding Number}" />
        </StackPanel>
    </DataTemplate>

Это немного сбивает с толку, потому что я назвал DependencyProperty Number в UpDown UserControl так же, как свойство в классе NumberGroup.NumberGroup просто:

public class NumberGroup
{
    public int Number { get; set; }
}

Когда я запускаю приложение, я уже знаю, что оно не будет работать, потому что окно «Вывод» говорит мне:

System.Windows.Data Error: 39 : BindingExpression path error: 'Number' property not found on 'object' ''UpDown' (Name='')'. BindingExpression:Path=Number; DataItem='UpDown' (Name=''); target element is 'UpDown' (Name=''); target property is 'Number' (type 'Int32')

ОК, поэтому оно привязано кUserControl вместо ListItem ... это не может быть записано.В качестве теста я удалил DataTemplate из определения Resources и ListBox и перезапустил его.В ListBox я получил кучу NumberGroup s, и это именно то, что я ожидал!

Так почему же, когда я делаю это, он связывается с ListItem, но когда я определяю ItemTemplateон хочет привязать к элементу управления UpDown?Любое объяснение будет очень ценно.Я просмотрел статьи доктора WPF и не понимаю, почему это произойдет.

ОБНОВЛЕНИЕ

Хорошо, я выяснил кое-что, связанное с моей проблемой.В UserControl я устанавливаю DataContext для себя, чтобы я мог обрабатывать ICommand с кнопками «Вверх» и «Вниз».Но по какой-то причине я еще не понимаю, это портит привязку данных для ListItem!Почему это произойдет, если UserControl содержится внутри ListItem?

1 Ответ

1 голос
/ 22 июля 2010

Когда вы сами устанавливаете DataContext UserControl внутри себя, вы получаете точно такой же эффект, как если бы вы делали это:

<updown:UpDown DataContext="{Binding RelativeSource={RelativeSource Self}}" />

Очевидно, что теперь любые установленные вами привязки, для которых не определен явный источник, будут использоватьэлемент управления UpDown как их контекст.Поэтому, когда вы пытаетесь привязать свойство Number, оно ищет свойство Number в UpDown, а не данные вашего ListBoxItem.Это именно то, о чем говорит ваша ошибка.

Чтобы избежать этого, измените настройку DataContext в вашем UserControl, чтобы применить его к элементу внутри элемента управления, например, к корневой сетке макета с x: Name.

<Grid x:Name="LayoutRoot">
...
</Grid>

И установите DataContext либо в коде, либо в XAML.

LayoutRoot.DataContext = this;
...