views:

316

answers:

2

Hello,

how can I bind the Content of a ContentControl to an ObservableCollection. The control should show an object as content only if the ObservableColelction contains exactly one object (the object to be shown).

Thanks, Walter

+1  A: 
IanR
This looks good so far, but if the Collection is initially empty and i add an Element later (maybe by clicking a button), the InvalidCountGrid is removed mut the Data of the single Element in the Colection is not shown. I think the CurrentItem of the OC is still null?
Walter
updated answer :)
IanR
To me this seems to be an extremely complex way of doing it. See my answer for a simple solution to the same problem.
Ray Burns
A: 

This is easy. Just use this DataTemplate:

<DataTemplate x:Key="ShowItemIfExactlyOneItem">

  <ItemsControl x:Name="ic">
    <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate><Grid/></ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
  </ItemsControl>

  <DataTemplate.Triggers>
    <DataTrigger Binding="{Binding Count}" Value="1">
      <Setter TargetName="ic" Property="ItemsSource" Value="{Binding}" />
    </DataTrigger>
  </DataTemplate.Triggers>

</DataTemplate>

This is used as the ContentTemplate of your ContentControl. For example:

<Button Content="{Binding observableCollection}"
        ContentTemplate="{StaticResource ShowItemIfExactlyOneItem}" />

That's all you need to do.

How it works: The template normally contains an ItemsControl with no items, which is invisible and has no size. But if the ObservableCollection that is set as Content ever has exactly one item in it (Count==1), the trigger fires and sets the ItemsSource of the ItmesControl, causing the single item to display using a Grid for a panel. The Grid template is required because the default panel (StackPanel) does not allow its content to expand to fill the available space.

Note: If you also want to specify a DataTemplate for the item itself rather than using the default template, set the "ItemTemplate" property of the ItemsControl.

Ray Burns