ListBox ItemTemplate непостоянен с данными CLR и UserControl

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

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

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

My 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 из определения ресурсов и ListBox и повторно запустил его. В ListBox я получил кучу NumberGroup, чего я и ожидал!

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

ОБНОВЛЕНИЕ

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


person Dave    schedule 22.07.2010    source источник


Ответы (1)


Когда вы устанавливаете 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;
person John Bowen    schedule 22.07.2010
comment
Спасибо за совет! Как вы сказали, это избавляет от сообщения об ошибке, которое указывает, что привязка была к UpDown UserControl, а не к данным CLR. Теперь моя проблема в том, что я не могу установить текст в моем элементе управления UpDown. У меня есть DependencyProperty для Number, потому что я хотел бы сделать что-то вроде <updown:UpDown Number="{Binding ClientNumber}">, но, похоже, это не работает. Даже жесткое кодирование Number не работает, поэтому я предполагаю, что мое DependencyProperty не работает (но оно работает внутренне, потому что мои команды кнопок вверх и вниз могут изменить значение Number!) - person Dave; 22.07.2010
comment
интересно, я поместил свой контроль в тестовое приложение, и установка числа через окно работала нормально ... но установка его из моего UserControl (у меня есть UserControl внутри UserControl) - нет. - person Dave; 22.07.2010
comment
глупая ошибка кодера, все отлично работает, еще раз спасибо за полезный совет! - person Dave; 22.07.2010