Search code examples
wpfvisual-studio-2010listboxdatatemplateobservablecollection

ListBox defaulting to ToString() for items despite DataTemplate


I'm trying to add a simple visual to my application representing the print margins on a page to help a user avoid positioning data that might be out of range. To do this, I have a method which takes paper size, DPI, and margin settings information and uses it to make an ObservableCollection(of Rect) which contains four Rect's, one for each edge of the page. A ListBox in XAML is bound to the collection by way of a GetMargins() property that returns the collection. I have defined a DataTemplate for the Page in the Resource section of the Grid hosting the ListBox, and the ListBox uses a Canvas in ItemsPanelTemplate so that I can position and size some Rectangles on the page using each Rect's x, y, width, and height. Here's the XAML:

In Grid.Resources:

<!--
A data template for the page margins.
-->
<DataTemplate DataType="{x:Type local:Page}">
    <Grid>
        <Rectangle
            Width="{Binding Width}"
            Height="{Binding Height}"
            Fill="LightGreen"
            Opacity="0.5"
            />
    </Grid>             
</DataTemplate>

In Grid:

<!--
Listbox to present the page margins.
-->
<ListBox
    x:Name="PageMarginsListBox"
    ItemsSource="{Binding GetMargins}"
    Background="Transparent"
    IsHitTestVisible="False"
    >
    <ListBox.ItemsPanel>
         <ItemsPanelTemplate>
              <Canvas />
         </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.ItemContainerStyle>
         <Style TargetType="ListBoxItem">
              <Setter
                   Property="Canvas.Left"
                   Value="{Binding X}"                        
                   />
              <Setter
                   Property="Canvas.Top"
                   Value="{Binding Y}"                        
                   />
         </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

When I run the application, the above code results in string output instead of light green rectangles on the page's borders. For example, the Rect for the left-side margin will appear as "0,0,75,1650" instead of a rectangle that is 75px wide and spans the height of the whole page. The bottom margin string is positioned in the bottom left corner, and the right margin appears in the top right corner, as expected. So the binding is working and they are positioned correctly, but not drawn for some reason.

What I find interesting about this is that I have another ObservableCollection filled with objects of my own design, which are positioned and styled in almost the same way on the Page's surface. The XAML for the ListBox bound to that collection is set up exactly the same way, but with a somewhat more complex DataTemplate for each item (9 rectangles instead of just one). It works quite well. They both live in the same Grid, too.

So I don't see where I'm going wrong with this one, except that it's probably a DataTemplate issue if I'm getting toString() output. Thoughts? Spot my mistake?

Thanks :)


Solution

  • It seems to me You have wrong DataType in DataTemplate. GetMargins() returns ObservableCollection of Rect right? Then ListboxItems are created from Rect's while Your DataTemplate is defined for Page class.