开发者

ListBox ItemTemplate is fickle with CLR and UserControl data

I wrote a simple UpDown UserControl for my application. I am rendering it in a ListBox so that as UpDown controls get added, they stack up horizontally.

开发者_运维百科

My UserControl has one DependencyProperty that corresponds to the number inside of the UpDown control, called NumberProperty.

I add multiple UpDown controls to the ListBox via databinding, where the ItemsSource for the ListBox is merely an ObservableCollection<NumberGroup> called NumberGroups. Each NumberGroup just has a member called Number, and I want this number to appear in its respective UpDown control when the ListBox is rendered.

My ListBox is defined in XAML like this:

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

and the DataTemplate for the ListBox is:

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

It's a little confusing because I named the DependencyProperty Number in the UpDown UserControl the same as the property in the NumberGroup class. NumberGroup is merely:

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

When I run the application, I already know it's not going to work because the Output window tells me:

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')

OK, so it's binding to the UserControl instead of the ListItem... that can't be write. So as a test, I removed the DataTemplate from the Resources and ListBox definition and re-ran it. In the ListBox, I got a bunch of NumberGroups, which is exactly what I would expect!

So how come when I do this, it seems to bind against the ListItem, but when I define the ItemTemplate it wants to bind to the UpDown control? Any explanation would be really appreciated. I've gone over the Dr. WPF articles and don't see why this would happen.

UPDATE

Ok, I figured out something related to my problem. Within the UserControl, I am setting the DataContext to itself, so that I can process the ICommands that deal with the Up and Down buttons. But for some reason I don't yet understand, it messes with the databinding for the ListItem! Why would this happen if the UserControl is contained inside of the ListItem?


When you set the UserControl's DataContext internally to itself you're getting exactly the same effect as if you did this:

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

Obviously now any Bindings that you set which have no explicit Source defined will use the UpDown control as their context. So when you're trying to bind to the Number property it's looking for a Number property on UpDown instead of your ListBoxItem's data. This is exactly what your error is telling you.

To avoid this change your DataContext setting in your UserControl to apply to an element inside the control, like a root layout Grid with an x:Name.

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

And set DataContext either in code or XAML.

LayoutRoot.DataContext = this;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜