I am creating a Windows app using C# and WPF, using MVVM. I am trying to create a collapsible items control, in order to display items from a collection. When expanding each item, a groupbox containing the item’s properties should be displayed. I have the following inside a UserControl:
<UserControl.Resources>
<SolidColorBrush x:Key="GlyphBrush" Color="#444" />
<ControlTemplate x:Key="toggleButtonTemplate" TargetType="ToggleButton">
<Grid
Width="15"
Height="13"
Background="Transparent">
<Path x:Name="ExpandPath"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="1,1,1,1"
Fill="{StaticResource GlyphBrush}"
Data="M 4 0 L 8 4 L 4 8 Z"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked"
Value="True">
<Setter Property="Data"
TargetName="ExpandPath"
Value="M 0 4 L 8 4 L 4 8 Z"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="toggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Template" Value="{StaticResource toggleButtonTemplate}" />
</Style>
<BooleanToVisibilityConverter x:Key="VisibilityOfBool" />
<Style x:Key="CollapsibleListStyle" TargetType="{x:Type ItemsControl}">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style>
<Setter Property="Control.Margin" Value="5" />
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" Focusable="False">
</ContentPresenter>
<ToggleButton x:Name="toggleButton"
Grid.Column="1" IsChecked="False" Margin="3.5"
Style="{StaticResource toggleButtonStyle}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<WrapPanel>
<ItemsControl Name="itemsList"
Style="{StaticResource CollapsibleListStyle}"
ItemsSource="{Binding ViewModel.Items}"
Margin="0,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Grid.Column="0"
FontWeight="DemiBold" VerticalAlignment="Center"/>
<GroupBox Header="Properties" Grid.Column="1" Margin="5"
Visibility="{Binding ElementName=toggleButton,
Path=IsChecked, Converter={StaticResource VisibilityOfBool}}">
<WrapPanel HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal" Margin="5">
<TextBlock Text="Code: "/>
<TextBlock Text="{Binding ItemCode}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5">
<TextBlock Text="Key: "/>
<TextBlock Text="{Binding ItemKey}"/>
</StackPanel>
</WrapPanel>
</GroupBox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</WrapPanel>
This produces the following error at runtime:
System.Windows.Data Error: 4 : Cannot find source for binding with
reference ‘ElementName=toggleButton’.
BindingExpression:Path=IsChecked; DataItem=null; target element
is ‘GroupBox’ (Name=”); target property is ‘Visibility’ (type
‘Visibility’)
so the toggle button is not displayed.
At a different place in my application, I have used the above, but replaced ItemsControl with a ListBox, to get a collapsible list box, and the code works as it should.
However, here I do not want the selection functionality.
Can anyone please help with this?
Thank you, Brian
You should always specify the
TargetTypeif you know it, your style does not apply properly because you make it generic by not setting it and at the same time setting properties which do not exist on the container and hence are ignored.Change the
TargetTypetoContentPresenterand you will no longer be able to set aTemplate:You need to move everything into the
ItemTemplateas there is noControlTemplateto be set.