I'm trying to use an XML data source and a data template to generate some TextBlock elements from this data and present them using an ItemsControl. The TextBlocks are generated correctly, but I can't figure out how to position them on a Grid or Canvas panel. It seems the attached properties (Grid.Column, Grid.Row, Canvas.Left, etc) that I define on the TextBlocks are somehow ignored.
This is the XAML code I'm using:
<StackPanel xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
<StackPanel.Resources>
<XmlDataProvider x:Key="dataSource" XPath="/Test">
<Test xmlns="">
<Key Name="test"/>
</Test>
</XmlDataProvider>
<DataTemplate x:Key="dataTemplate">
<TextBlock Canvas.Left="20" Canvas.Top="20" Text="{Binding XPath=@Name}"/>
</DataTemplate>
<Canvas x:Key="dataCanvas"/>
</StackPanel.Resources>
<ItemsControl ItemsSource="{Binding Source={StaticResource dataSource}, XPath=Key}" ItemTemplate="{StaticResource dataTemplate}" ItemsPanel="{StaticResource dataCanvas}" />
</StackPanel>
This XAML markup generates a single TextBlock element as defined in the XML source but doesn't position it correctly on the Canvas. I get the same results with a Grid panel. What is wrong
Also, when I tried traversing the logical tree (using LogicalTreeHelper) to see if I was missing something I couldn't get past the ItemsControl element; it said it had no children. Does the data template generate a logical tree under the ItemsControl element If so, how can one access this tree

Positioning elements generated by a data template on a Grid or Canvas
arpicheck
Vertexwahn
Can anyone explain why the following (exerpt from the sample) does not compile:
<ItemsControl ItemsSource="{Binding Source={StaticResource sudokuxml}, XPath=testitem}"
ItemTemplate="{StaticResource itemdatatemplate}">
<ItemsControl.Style>
<Style TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Grid IsItemsHost="true">
<RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</RowDefinitions>
<ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</ColumnDefinitions>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.Style>
and the if I leave the "RowDefinitions" and "ColumnDefinitions" out, it DOES compile I seems awkward as RowDefinitions and ColumnDefinitions seem to me the only two valid descendants for a Grid element
How did you guys learn about contentpresenter and itemscontrol Any good references It seems like they are certainly not encouraged to be used when reading the docs. Soooo cool I got this to work!
Thanks a lot,
Best regards,
Christof
tao84
<StackPanel xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
<StackPanel.Resources>
<XmlDataProvider x:Key="mapData" XPath="/Map">
<Map xmlns="">
<Tile X="0" Y="0" Image="0.png"/>
<Tile X="1" Y="0" Image="1.png"/>
<Tile X="0" Y="1" Image="2.png"/>
<Tile X="1" Y="1" Image="3.png"/>
</Map>
</XmlDataProvider>
</StackPanel.Resources>
<ItemsControl ItemsSource="{Binding Source={StaticResource mapData}, XPath=Tile}">
<ItemsControl.ItemsPanel>
<Grid>
<RowDefinition/><RowDefinition/>
<ColumnDefinition/><ColumnDefinition/>
</Grid>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding XPath=@Image}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Grid.Column" Value="{Binding XPath=@X}"/>
<Setter Property="Grid.Row" Value="{Binding XPath=@Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</StackPanel>
With this code all the items appear on top of each other, even though I define the Grid.Row and Grid.Column attached properties of their containers correctly. It seems the Grid object is instantiated with no rows and columns, even though the <RowDefinition/> and <ColumnDefinition/> tags are there.
On the other hand, if I define the items panel through a style that overrides the control template for the ItemsControl I get the correct behavior:
<StackPanel xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
<StackPanel.Resources>
<XmlDataProvider x:Key="mapData" XPath="/Map">
<Map xmlns="">
<Tile X="0" Y="0" Image="0.png"/>
<Tile X="1" Y="0" Image="1.png"/>
<Tile X="0" Y="1" Image="2.png"/>
<Tile X="1" Y="1" Image="3.png"/>
</Map>
</XmlDataProvider>
</StackPanel.Resources>
<ItemsControl ItemsSource="{Binding Source={StaticResource mapData}, XPath=Tile}">
<ItemsControl.Style>
<Style TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Grid IsItemsHost="true">
<RowDefinition/><RowDefinition/>
<ColumnDefinition/><ColumnDefinition/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.Style>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding XPath=@Image}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Grid.Column" Value="{Binding XPath=@X}"/>
<Setter Property="Grid.Row" Value="{Binding XPath=@Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</StackPanel>
What is the difference between the two alternatives
singlark
In your case, since you're using a Grid, you could set the column and row definitions in the ItemsPanelTemplate (in my case, I just set the Height of the Canvas).
richardghome
If I'm not mistaken, ContentPresenter is just an element whose only purpose is displaying the content for a ContentControl. It acts as a placeholder that means "the content for the control goes here". If you look at the CheckBox's template, for instance, you'll see there's a ContentPresenter placed at the point where the checkbox's content should go:
http://winfx.msdn.microsoft.com/library/default.asp url=/library/en-us/wcp_conceptual/html/bfdaec96-d101-4d3d-864d-c27e6b621d03.asp
Same for the other ContentControls (e.g. Button).
As for where I learnt about ContentPresenter and ContentControl, I believe it was mostly from posts on this forum and some Avalon bloggers.
MFC
I kept on trying to get this to work but for some reason:
- columndefinitions and rowdefinitions are not dependencyproperties on a grid and so they are not allowed to be set from within a style
- also setting the number of rows and colums in a controltemplate does not work
I think this is a great post as it show how to generate databound items that are positioned automatically in a grid!! I assume that a lot of people are looking for some non-existent "datagrid" control like they had in classic winforms. While the way to accomplish it is exactly using the code posted in this sample.
Thanks for any help!
Best regards!
Christof
tom-
Thanks for your answer so much Javier. But is this valid xaml please :
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Grid IsItemsHost="true">
<RowDefinition/><RowDefinition/>
<ColumnDefinition/><ColumnDefinition/>
</Grid>
</ControlTemplate>
I was also struggling with where to set the amount of rows and columns in the grid. Can you copy paste the source maybe :-)
Is the contentpresenter a real control Or is it some GUI-less abstract class that accidently can be used for this purpose...
I would like to understand more of this I guess. All I have read is the Oreilly book; so any good other resources would be welcome too!
Best regards and thanks again for your time!
Christof
Beaver01
<StackPanel xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
<StackPanel.Resources>
<XmlDataProvider x:Key="dataSource" XPath="/Test">
<Test xmlns="">
<Key Name="test"/>
</Test>
</XmlDataProvider>
<DataTemplate x:Key="dataTemplate">
<TextBlock Text="{Binding XPath=@Name}"/>
</DataTemplate>
<Style x:Key="MyContainerStyle">
<Setter Property="Canvas.Left" Value="20"/>
<Setter Property="Canvas.Top" Value="20"/>
</Style>
<Canvas x:Key="dataCanvas"/>
</StackPanel.Resources>
<ItemsControl ItemsSource="{Binding Source={StaticResource dataSource}, XPath=Key}" ItemTemplate="{StaticResource dataTemplate}" ItemsPanel="{StaticResource dataCanvas}" ItemContainerStyle="{StaticResource MyContainerStyle}"/>
</StackPanel>
sirbill
<StackPanel xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
...
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Grid.Column" Value="{Binding XPath=@X}"/>
<Setter Property="Grid.Row" Value="{Binding XPath=@Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</StackPanel>
Site Defense
At this moment, the most up to date information is in the Platform SDK. Chris Sells' book is slightly out of date (e.g. the stuff about navigation is obsolete), and the articles on MSDN are much more out of date. I watched all the PDC2005 WPF presentations, they give a good overview of all the WPF features and they are reasonably up to date (apart from the Nov CTP changes). And I read the blogs of the Avalon bloggers and read this forum.