17

I have an ItemsControl that is data bound to a list of decimals. I need to add one extra control to the ItemsControl (an option to specify the number manually). Is there a way to do this in XAML? I know I can manually add the item in the code behind, but I'm trying to understand WPF a little better and want to see if there is a declarative way to do it.

Note that modifying the list I'm binding to so that it includes the extra button (possibly by changing to a list of strings instead of decimals) isn't a good alternative because I want to attach a command to that last button.

Also, adding an extra button after the ItemsControl isn't a good option either, because my control uses a UniformGrid and I want my extra control in that same grid.

Here is my XAML:

<ItemsControl ItemsSource="{Binding PossibleAmounts}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Name="ButtonsGrid">
            </UniformGrid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button>
                <TextBlock Text="{Binding StringFormat='\{0:C\}'}"/>
            </Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Basically, I want one more button in the UniformGrid.

Eddie Deyo
  • 5,200
  • 8
  • 35
  • 35

2 Answers2

23

You can use the CompositeCollection class for this purpose, it combines multiple collections or individual items as the ItemsSource for an ItemsControl.

There's a good example in the MSDN article, or here's another one:

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:sys="clr-namespace:System;assembly=mscorlib"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid.Resources>
        <x:Array x:Key="intData" Type="{x:Type sys:Int32}">
            <sys:Int32>1</sys:Int32>
            <sys:Int32>2</sys:Int32>
            <sys:Int32>3</sys:Int32>
        </x:Array>
        <x:Array x:Key="stringData" Type="{x:Type sys:String}">
            <sys:String>Do</sys:String>
            <sys:String>Re</sys:String>
            <sys:String>Mi</sys:String>
        </x:Array>
    </Grid.Resources>
    <ListBox>
        <ListBox.ItemsSource>
            <CompositeCollection>
                <CollectionContainer Collection="{StaticResource intData}"/>
                <CollectionContainer Collection="{StaticResource stringData}"/>
                <ListBoxItem>One more item!</ListBoxItem>
                <ListBoxItem>Two more items!</ListBoxItem>
            </CompositeCollection>
        </ListBox.ItemsSource>
    </ListBox>
</Grid>
Robert Macnee
  • 11,650
  • 4
  • 40
  • 35
18

The problem with CompositeCollection, though, is that it doesn't inherit the parent element DataContext, so you won't be able to write:

<CollectionContainer Collection={Binding ...}" />

inside it - or rather it'll let you, but you won't get anything out of it. Since the original post required that - {Binding PossibleAmounts} - rather than binding to a StaticResource - it's not really a solution.

See:

http://blogs.msdn.com/nickkramer/archive/2006/08/18/705116.aspx

http://www.vistax64.com/avalon/90-compositecollections-collectioncontainer-binding-issue.html

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/bd1a78c1-67ef-4d1e-9cbe-70bbe8eb8b44/

Randolpho
  • 55,384
  • 17
  • 145
  • 179
  • This problem is solved by adding a freezable object to the resources that stores the binding and serves as the source for the collection property binding. – Dmitry Tashkinov Sep 17 '10 at 15:40
  • @DmitryTashkinov it would be interesting to have it explained why. – ANeves May 21 '15 at 16:24
  • @DmitryTashkinov Can you elaborate a little how can we achieve this? – Amir Mahdi Nassiri Jun 14 '18 at 16:25
  • Oh guys, It's been years. So why don't you add a resource and inside CompositeCollection add – Dmitry Tashkinov Jun 15 '18 at 09:15
  • Referring to @DmitryTashkinov 's comment about freezable - see https://stackoverflow.com/questions/2692175/freezable-datacontext, https://stackoverflow.com/questions/26364979/binding-doesnt-work-on-dependencyobject-created-in-xaml, https://stackoverflow.com/questions/19144410/dependencyobject-bypasses-dependencyproperty-system – StayOnTarget Jun 16 '20 at 14:05