This project has moved. For the latest updates, please go here.

custom ItemTemplate for ListBox in CollectionControl

Oct 28, 2013 at 9:11 AM
Hi,

I'm trying to apply a custom ItemTemplate to the ListBox inside the CollectionControl.
At the moment I have the following:
        <xctk:CollectionControl ItemsSource="{Binding Items}" NewItemTypes="{Binding Types, Mode=OneWay}">
            <xctk:CollectionControl.Style>
                <Style TargetType="xctk:CollectionControl">
                    <Setter Property="ListBox.ItemTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <TextBlock Text="{Binding}" Background="Blue"/>                                    
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </xctk:CollectionControl.Style>
        </xctk:CollectionControl>
Unfortunately nothing happens.
I'm relative new to WPF and have no idea what I'm doing wrong here.
If someone could give me a hint it would be much appreciated.

Regards
Peter
Developer
Oct 28, 2013 at 2:10 PM
Hi,

First, if the CollectionControl is empty, you need to set the DataContext for the CollectionControl, either in XAML or Code-Behind.

Second, using your way, or even when setting the CollectionControl.resources to modify the ListBox.ItemTemplate this way :
 <xctk:CollectionControl x:Name="_collectionControl" ItemsSource="{Binding Items}" NewItemTypes="{Binding Types, Mode=OneWay}">
         <xctk:CollectionControl.Resources>
            <Style TargetType="ListBox">
               <Setter Property="ListBox.ItemTemplate">
                  <Setter.Value>
                     <DataTemplate>
                        <TextBlock Text="{Binding}"
                                   Background="Blue" />
                     </DataTemplate>
                  </Setter.Value>
               </Setter>
            </Style>
         </xctk:CollectionControl.Resources>
it won't work.

That is because the Current CollectionControl already defines a ListBox.ItemTemplate. A solution is to redefine the implicit style of the CollectionControl. You can find the content in
-Toolkit/CollectionControl/Themes/Aero2.NormalColor.xaml (for windows8)
-Toolkit/CollectionControl/Themes/Generic.xaml (for Windows7)
Oct 28, 2013 at 4:39 PM
Thanks for your answer.

I'm afraid my understanding of Styles and Templates is not firm enough to understand where exactly the problem lies.
In my understanding Setters are used to set properties on existing controls (while DataTemplates are used to create controls). Styles apply Setters to controls of a certain type. So why can't I use a Style to set a new ItemTemplate on the listbox (and thus override the old one)?

If I understand your solution proposal correctly I'd have to replace the whole style with a slightly altered copy. That seems kind of inelegant to me.

Also: What is the difference between setting/adding a style to the Resource-dictionary and the Style-property?
Developer
Oct 29, 2013 at 1:14 PM
Hi pEnenkel,

Your understanding of styles and templates is right :
"Setters are used to set properties on existing controls (while DataTemplates are used to create controls). Styles apply Setters to controls of a certain type".

In your sample, you are defining a new style for the CollectionControl. So if you use a setter to set the Background property for example, the Background of the CollectionControl will be overriden.

The default CollectionControl contains a ListBox, and locally, this ListBox sets its ItemTemplate, overriding the default implicit Style of the ListBox. This means that a specific listBox is used in the CollectionControl.

Back to your sample, you are trying to modify ListBox.ItemTemplate fom CollectionControl, which is not present in CollectionControl.

A change can be made to satisfay your needs.

Go in :
-Toolkit/CollectionControl/Themes/Aero2.NormalColor.xaml (For Windows8)
-Toolkit/CollectionControl/Themes/Generic.xaml (For Windows 7)
and remove the "<ListBox.ItemTemplate> block" from the ListBox in the implicit Style of the collectionControl.
Then, add
 <Style.Resources>
         <Style TargetType="ListBox">
            <Setter Property="ItemTemplate">
               <Setter.Value>
                   <DataTemplate>
                     <TextBlock Text="{Binding Converter={StaticResource ObjectTypeToNameConverter}}"/>
                  </DataTemplate>
               </Setter.Value>
            </Setter>
         </Style>
      </Style.Resources>
right after the line
<Style TargetType="{x:Type local:CollectionControl}">
This will define an implicit style for the ListBox of the CollectionControl.

In your sample, you will now be able to just add an implicit style for the ListBox in the resource of the CollectionControl. This new ListBox style will override the default listBox style that you modified earlier. I hope I'm clear enough :-)

Here's your new sample :
  <xctk:CollectionControl ItemsSource="{Binding Items}" NewItemTypes="{Binding Types, Mode=OneWay}">
            <xctk:CollectionControl.Style>
                <Style TargetType="xctk:CollectionControl">
                     <Style.Resources>
                        <Style TargetType="ListBox">
                            <Setter Property="ItemTemplate">
                                <Setter.Value>
                                   <DataTemplate>
                                          <TextBlock Text="{Binding}" Background="Blue"/>
                                   </DataTemplate>
                              </Setter.Value>
                          </Setter>
                       </Style>
                    </Style.Resources>
                </Style>
            </xctk:CollectionControl.Style>
        </xctk:CollectionControl>
Finally, adding the style to a resource (like the implicit style of the ListBox in the resource of the CollectionControl style) will make sure this implicit style will be used only in the collectionControl, not anywhere else.
Developer
Mar 26, 2014 at 5:32 PM
Edited Mar 26, 2014 at 5:33 PM
answered